How to get week start and end date string in PostgreSQL?
Asked Answered
F

6

53

I am using PostgreSQL 8.3. I have a table like this:

id        regist_time        result
-----------------------------------
1     2012-07-09 15:00:08      3
2     2012-07-25 22:24:22      7
4     2012-07-07 22:24:22      8

regist_time's data type is timestamp.

I need to find a week time interval(start to end) and sum(result) as num.

I want to get the result as:

      week                    num    
---------------------------------
7/1/2012-7/7/2012              10
7/8/2012-7/14/2012              5
7/15/2012-7/21/2012             3
7/22/2012-7/28/2012            11

I can get the week number just in this year:

SELECT id,regis_time, EXTRACT(WEEK FROM regis_time) AS regweek
FROM tba

The key part is

EXTRACT(WEEK FROM regis_time) 

extract function can only get the week number in this year, how can I get start time to end time in one week?

Ferreira answered 1/8, 2012 at 14:55 Comment(0)
D
120

You can use date_trunc('week', ...).

For example:

SELECT date_trunc('week', '2012-07-25 22:24:22'::timestamp);
-> 2012-07-23 00:00:00

Then, you can convert this into a date, if you're not interested in a start time.

To get the end date too:

SELECT    date_trunc('week', '2012-07-25 22:24:22'::timestamp)::date
   || ' '
   || (date_trunc('week', '2012-07-25 22:24:22'::timestamp)+ '6 days'::interval)::date;

-> 2012-07-23 2012-07-29

(I've used the default formatting here, you can of course adapt this to use MM/DD/YYYY.)

Note that, if you want to make comparisons on timestamps, instead of using (date_trunc('week', ...) + '6 days'::interval, you might want to add an entire week and use a strict comparison for the end of the week.

This will exclude y timestamps on the last day of the week (since the cut-off time is midnight on the day).

    date_trunc('week', x)::date <= y::timestamp
AND y::timestamp <= (date_trunc('week', x) + '6 days'::interval)::date

This will include them:

    date_trunc('week', x)::date <= y::timestamp
AND y::timestamp < (date_trunc('week', x) + '1 week'::interval)

(That's in the rare cases when you can't use date_trunc on y directly.)


If your week starts on a Sunday, replacing date_trunc('week', x)::date with date_trunc('week', x + '1 day'::interval)::date - '1 day'::interval should work.

Dig answered 1/8, 2012 at 15:2 Comment(2)
This assumes that weeks start on Monday. Is there a way to do the same thing but with weeks that start on a Sunday?Dross
Thanks! Sorry, I'm not using SO very often. Upvoted! :DDross
S
18
select date_trunc('week', regist_time)::date || ' - ' ||
       (date_trunc('week', regist_time) + '6 days') ::date as Week,
       sum(result) Total
from YourTable
group by date_trunc('week', regist_time)
order by date_trunc('week', regist_time)

See proof of concept at SQLFiddle: http://sqlfiddle.com/#!1/9e821/1

Spleen answered 1/8, 2012 at 15:9 Comment(0)
I
5

This can help, a query to get all days of current week.

select cast(date_trunc('week', current_date) as date) + i
from generate_series(0,6) i

2015-08-17
2015-08-18
2015-08-19
2015-08-20
2015-08-21

To get week start and end date (as 0 for Monday and 4 for Friday):

select cast(date_trunc('week', current_date) as date) + 0 || '-->' ||  cast(date_trunc('week', current_date) as date) + 4;

2015-08-17-->2015-08-21

Isomerism answered 18/8, 2015 at 10:52 Comment(0)
L
3

It is

select to_date('2015-07', 'IYYY-IW');

use it in postgres

it will return

2015-02-09
Lustig answered 11/2, 2015 at 21:10 Comment(0)
H
0

If you want to get week start and end date with week start day is any day in the week (Monday, Tuesday, ...). You can use this way:

day_of_week_index mapping:

{
    'monday': 1,
    'tuesday': 2,
    'wednesday': 3,
    'thursday': 4,
    'friday': 5,
    'saturday': 6,
    'sunday': 7
}

Query template:

SELECT 
concat(
    CASE
        WHEN extract(ISODOW FROM datetime_column) < day_of_week_index THEN cast(date_trunc('week', datetime_column) AS date) - 8 + day_of_week_index
        ELSE cast(date_trunc('week', datetime_column) AS date) - 1 + day_of_week_index
    END, ' - ', 
    CASE
        WHEN extract(ISODOW FROM datetime_column) < day_of_week_index THEN cast(date_trunc('week', datetime_column) AS date) - 8 + day_of_week_index + 6
        ELSE cast(date_trunc('week', datetime_column) AS date) - 1 + day_of_week_index + 6
    END) 
FROM table_name;

Example:

Get week start and end date with week start day is Tuesday:

SELECT 
concat(
    CASE
        WHEN extract(ISODOW FROM TIMESTAMP '2021-12-01 03:00:00') < 2 THEN cast(date_trunc('week', TIMESTAMP '2021-12-01 03:00:00') AS date) - 8 + 2
        ELSE cast(date_trunc('week', TIMESTAMP '2021-12-01 03:00:00') AS date) - 1 + 2
    END, ' - ', 
    CASE
        WHEN extract(ISODOW FROM TIMESTAMP '2021-12-01 03:00:00') < 2 THEN cast(date_trunc('week', TIMESTAMP '2021-12-01 03:00:00') AS date) - 8 + 2 + 6
        ELSE cast(date_trunc('week', TIMESTAMP '2021-12-01 03:00:00') AS date) - 1 + 2 + 6
    END);

=> Result:

2021-11-30 - 2021-12-06

Note: You can change the day_of_week_index following the above mapping to determine the week start day (Monday, Tuesday, ..., Sunday)

Halvorson answered 15/12, 2021 at 10:10 Comment(0)
H
0

To get the start of the week as a date:

SELECT CAST(date_trunc('week', CURRENT_DATE) AS DATE);

To get the end of the week as a date:

SELECT CAST(date_trunc('week', CURRENT_DATE) AS DATE) + 5;

You can always play around with the query by adding integers that represent the days to the end.

Hyalo answered 13/2, 2024 at 9:59 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.