Reputation: 6603
I can create user defined function and compute total no of days for given month. Is there a direct way of getting total of no days in given month for given date
eg.
select date_t, some_inbuilt_function_get_total_no_of_days_in_month(date_t)
There is month function to get month from given date, similarly there is date function, so I can go to start of the month. There is date difference function but there is no way to go to end of the month.
Reference: https://cloud.google.com/bigquery/docs/reference/legacy-sql
Upvotes: 8
Views: 14295
Reputation: 1
Try running this query. It first get all the dates between date input, then calculates the number of days in the month and after that the remaining days in the mont:
WITH
dates AS(
SELECT
date
FROM
UNNEST(GENERATE_DATE_ARRAY(DATE('2022-05-01'), DATE('2022-06-30')) ) AS date
ORDER BY
date ASC),
months AS(
SELECT
date,
EXTRACT(month
FROM
date) AS month
FROM
dates
GROUP BY
1,
2)
SELECT
date,
month,
COUNT(date) OVER (PARTITION BY month) AS month_day_count,
(COUNT(date) OVER (PARTITION BY month) - ROW_NUMBER() OVER(PARTITION by month)) +1 as month_days_left
FROM
months
Upvotes: 0
Reputation: 747
A simpler way would be just
EXTRACT(DAY FROM LAST_DAY(<DATE>))
As a function
CREATE TEMP FUNCTION DaysInMonth(d DATE) AS (
EXTRACT(DAY FROM LAST_DAY(d))
);
SELECT DaysInMonth('2017-01-17');
Upvotes: 16
Reputation: 21
This is my solution, just replace "2020-06-01" with your value:
EXTRACT(DAY FROM (DATE_SUB(DATE_TRUNC(DATE_ADD("2020-06-01", INTERVAL 1 MONTH), MONTH),INTERVAL 1 DAY)))
Upvotes: 2
Reputation: 41
I wanted to calculate the number of days in the current month and came up with the following solution based on Pradeep's answer:
select distinct
extract(DAY FROM
date_sub(date(CASE WHEN extract(MONTH from current_timestamp()) < 12 THEN extract(YEAR from current_timestamp()) -- but if this is 12, make it 1
ELSE extract(YEAR from current_timestamp()) + 1
END
,CASE WHEN extract(MONTH from current_timestamp()) < 12 THEN extract(MONTH from current_timestamp()) + 1
ELSE 1 --if it's decemer, the next month is january.
END
,1), INTERVAL 1 DAY)) DAYS_IN_MONTH
Upvotes: 0
Reputation: 172994
This can be matter of aesthetic preferences, but below looks more elegant to me
#standardSQL
CREATE TEMP FUNCTION DaysInMonth(d DATE) AS (
32 - EXTRACT(DAY FROM DATE_ADD(DATE_TRUNC(d, MONTH), INTERVAL 31 DAY))
);
SELECT DaysInMonth('2017-01-17');
And somehow I feel will be more optimal on big volume (if there is any use case for this)
Below is yet another version - less optimal
#standardSQL
CREATE TEMP FUNCTION DaysInMonth(d DATE) AS (
EXTRACT(DAY FROM DATE_SUB(DATE_ADD(d, INTERVAL 1 MONTH),
INTERVAL EXTRACT(DAY FROM d) DAY))
);
SELECT DaysInMonth('2017-01-17')
And if for any reason you need it in BigQuery Legacy SQL, check below example (but still consider migrating to Standard SQL)
#legacySQL
SELECT
32 - DAY(DATE_ADD(UTC_USEC_TO_MONTH(PARSE_UTC_USEC(d)),31,'DAY')) as DaysInMonth
FROM (SELECT '2017-01-17' as d)
Upvotes: 10
Reputation: 33745
It's easier using standard SQL. You can define your own function to simplify your query, too.
#standardSQL
CREATE TEMP FUNCTION DaysInMonth(d DATE) AS (
DATE_DIFF(DATE_TRUNC(DATE_ADD(d, INTERVAL 1 MONTH), MONTH),
DATE_TRUNC(d, MONTH), DAY)
);
SELECT DaysInMonth('2017-01-17');
Upvotes: 4
Reputation: 6603
I found one way to go to end of the month,
We can use DATE ADD function to go to next month and then substract 1 day to go to end of the month.
SELECT
DATE_ADD(TIMESTAMP(CONCAT(STRING(YEAR(DATE_ADD(TIMESTAMP("2017-1-12"),1, "Month"))),"-",STRING(MONTH(DATE_ADD(TIMESTAMP("2017-1-12"),1, "Month"))),"-1")), -1, "DAY")
Here is the answer: Just replace 2017-1-12 with desired date
SELECT
DATEDIFF(TIMESTAMP(CONCAT(STRING(YEAR(DATE_ADD(TIMESTAMP("2017-1-12"),1, "Month"))),"-",STRING(MONTH(DATE_ADD(TIMESTAMP("2017-1-12"),1, "Month"))),"-1")),
TIMESTAMP(CONCAT(STRING(YEAR(TIMESTAMP("2017-1-12"))),"-",STRING(MONTH(TIMESTAMP("2017-1-12"))), "-1")))
Upvotes: 0