I'm reading this SO post and am confused. Suppose I have a field that I've been told from our data engineering team is in UTC time. How can I cast it as PST (Pacific time, California)?
select
'2021-02-12 05:27:51' as if_this_is_already_utc_then,
'2021-02-12 05:27:51' at time zone 'pst' as is_this_pst,
'2021-02-12 05:27:51' at time zone 'utc' at time zone 'pst' as or_is_this_pst
Returns:
The two attempts at PST show different timestamps. Which is correct, if any? I'm confused because on the linked post they first seem to convert to UTC and then again to EST. Which do I need here if I know that the original timestamp is UTC and I want to get it to PST California?
Related
published is timestamp with time zone stored as UTC.
gps_coordinates is geography(Point,4326).
SELECT
ST_MakeLine(pp.Gps_Coordinates::geometry ORDER BY pp.Published) As DailyRoute,
pp.Published::date As DayOf
FROM xxxx As pp
WHERE pp.Id = 'xxxxxxxx'
GROUP BY DayOf
I am trying to get all of the data for the Id by day but in the timezone of the person who requested it, so if in CST everything that happened between 00:00:00 CST and 23:59:59 CST, or if in EST everything that happened between 00:00:00 EST and 23:59:59 EST.
What is the best way to rework this query to get the data using this information?
When I tried:
SELECT
ST_MakeLine(pp.Gps_Coordinates::geometry ORDER BY pp.Published) As DailyRoute,
pp.Published::date AT TIME ZONE 'CST' As DayOf
FROM xxxx As pp
WHERE pp.Id = 'xxxxxxxx'
GROUP BY DayOf
The dayof results in 2018-11-25 18:00:00, this is not what I want. I want to group by everything during the day based on the time of day in the Local Time Zone.
I want to group by everything during the day based on the time of day in the Local Time Zone.
If by "local time zone" you mean the user-provided 'CST', then use:
(pp.Published AT TIME ZONE 'CST')::date AS DayOf
Instead of
pp.Published::date AT TIME ZONE 'CST' As DayOf
If you cast to date first, you get the date as defined by the timezone setting of the current session (show timezone;). The following AT TIME ZONE construct first coerces the given date value to a timestamptz (timestamp with time zone) representing 00:00 of the given date for the current timezone setting, before computing the respective timestamp without time zone for the given time zone ('CST') - not what you want.
Related:
Ignoring time zones altogether in Rails and PostgreSQL
How to convert given UTC date time to PST date time, by keeping the daylight stuff in time calculations?
Note that the server I am hitting is in utc. I mean, GETDATE() = GETUTCDATE().
Also, we can't use AT TIME ZONE, as DB is on older SQL Server.
Thanks in advance for the help.
Search the site, example: Convert Datetime column from UTC to local time in select statement
Read the link above, also include daylight stuff in there for some of the responses too.
I have a pg database with a column type timestamp with time zone. I inserted the following date:
2016-08-01 00:00:00 GMT
However, in the database, it shows up as:
2016-07-31 20:00:00-04
Does anyone know what might be going on?
Thanks in advance!
Despite the name, TIMESTAMP WITH TIME ZONE doesn't actually store the time zone. It uses the session's time zone to normalize to UTC, and stores UTC. On retrieval it converts back from UTC to the session time zone.
You can change the session time zone by using the SET TIME ZONE command. Preferably, you should use the standard IANA time zone identifiers. For example:
SET TIME ZONE 'Europe/Paris'
or
SET TIME ZONE 'UTC'
Alternatively use the TIMESTAMP [WITHOUT TIME ZONE] type instead, which does no conversions.
I am building an application that needs to handle different timezones, including timezones with daylight savings time. I am storing all the dates/times using Postgressql's timestamp with timezone data type, and all are stored in the UTC timezone (I modified the timezone entry in postgresql.conf).
Here is an example table that I have created:
CREATE TABLE category_city
(
category_city_id serial NOT NULL,
appt_start_time timestamp(0) with time zone,
appt_end_time timestamp(0) with time zone,
appt_days_of_week character varying,
CONSTRAINT category_city_pkey PRIMARY KEY (category_city_id )
);
I have been testing some conversions using the 'America\Edmonton' timezone. Currently, this timezone is 6 hours behind UTC. I have a timestamp in this table that has the value 1970-01-01 15:00:00+00.
Now I perform this query:
SELECT appt_start_time at time zone 'America/Edmonton' as start
FROM category_city
This should give me the timestamp 1970-01-01 09:00:00+00, but instead it gives me the timestamp 1970-01-01 08:00:00+00, an offset of -7. which is the correct offset when not in DST, but is obviously not correct right now (DST is in effect).
I must be missing something because I'm sure I'm not the only one that needs to handle different timezones with DST.
The time on my server is correct, this is the output of the date command on Ubuntu:
Wed Apr 30 17:11:59 MDT 2014
Can anyone see something that I am overlooking, or has any experienced something similar and found a way to workaround it? Any help would be appreciated!
At 1970-01-01 09:00:00+00 the time at the timezone 'America/Edmonton' was 1970-01-01 08:00:00 regardless of when you ask. If you want the time at a specific timezone you need to make it explicit:
select '1970-01-01 15:00:00+00' at time zone 'MST' as start;
start
---------------------
1970-01-01 08:00:00
select '1970-01-01 15:00:00+00' at time zone 'MDT' as start;
start
---------------------
1970-01-01 09:00:00
I guess it is easy to see above why that time at the MDT timezone will always be the same.
I'm having an issue selecting dates properly from Postgres - they are being stored in UTC, but
not converting with the Date() function properly.
Converting the timestamp to a date gives me the wrong date if it's past 4pm PST.
2012-06-21 should be 2012-06-20 in this case.
The starts_at column datatype is timestamp without time zone. Here are my queries:
Without converting to PST timezone:
Select starts_at from schedules where id = 40;
starts_at
---------------------
2012-06-21 01:00:00
Converting gives this:
Select (starts_at at time zone 'pst') from schedules where id = 40;
timezone
------------------------
2012-06-21 02:00:00-07
But neither convert to the correct date in the timezone.
Basically what you want is:
$ select starts_at AT TIME ZONE 'UTC' AT TIME ZONE 'US/Pacific' from schedules where id = 40
I got the solution from this article is below, which is straight GOLD!!! It explains this non-trivial issue very clearly, give it a read if you wish to understand pstgrsql TZ management better.
Expressing PostgreSQL timestamps without zones in local time
Here is what is going on. First you should know that 'PST timezone is 8 hours behind UTC timezone so for instance Jan 1st 2014, 4:30 PM PST (Wed, 01 Jan 2014 16:00:30 -0800) is equivalent to Jan 2nd 2014, 00:30 AM UTC (Thu, 02 Jan 2014 00:00:30 +0000). Any time after 4:00pm in PST slips over to the next day, interpreted as UTC.
Also, as Erwin Brandstetter mentioned above, postresql has two type of timestamps data type, one with a timezone and one without.
If your timestamps include a timezone, then a simple:
$ select starts_at AT TIME ZONE 'US/Pacific' from schedules where id = 40
will work. However if your timestamp is timezoneless, executing the above command will not work, and you must FIRST convert your timezoneless timestamp to a timestamp with a timezone, namely a UTC timezone, and ONLY THEN convert it to your desired 'PST' or 'US/Pacific' (which are the same up to some daylight saving time issues. I think you should be fine with either).
Let me demonstrate with an example where I create a timezoneless timestamp. Let's assume for convenience that our local timezone is indeed 'PST' (if it weren't then it gets a tiny bit more complicated which is unnecessary for the purpose of this explanation).
Say I have:
$ select timestamp '2014-01-2 00:30:00' AS a, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'UTC' AS b, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'UTC' AT TIME ZONE 'PST' AS c, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'PST' AS d
This will yield:
"a"=>"2014-01-02 00:30:00" (This is the timezoneless timestamp)
"b"=>"2014-01-02 00:30:00+00" (This is the UTC TZ timestamp, note that up to a timezone, it is equivalent to the timezoneless one)
"c"=>"2014-01-01 16:30:00" (This is the correct 'PST' TZ conversion of the UTC timezone, if you read the documentation postgresql will not print the actual TZ for this conversion)
"d"=>"2014-01-02 08:30:00+00"
The last timestamp is the reason for all the confusion regarding converting timezoneless timestamp from UTC to 'PST' in postgresql. When we write:
timestamp '2014-01-2 00:30:00' AT TIME ZONE 'PST' AS d
We are taking a timezoneless timestamp and try to convert it to 'PST TZ (we indirectly assume that postgresql will understand that we want it to convert the timestamp from a UTC TZ, but postresql has plans of its own!). In practice, what postgresql does is it takes the timezoneless timestamp ('2014-01-2 00:30:00) and treats it as if it WERE ALREADY a 'PST' TZ timestamp (i.e: 2014-01-2 00:30:00 -0800) and converts that to UTC timezone!!! So it actually pushes it 8 hours ahead instead of back! Thus we get (2014-01-02 08:30:00+00).
Anyway, this last (un-intuitive) behavior is the cause of all confusion. Read the article if you want a more thorough explanation, I actually got results which are a bit different then their on this last part, but the general idea is the same.
I don't see the exact type of starts_at in your question. You really should include this information, it is the key to the solution. I'll have to guess.
PostgreSQL always stores UTC time for the type timestamp with time zone internally. Input and output (display) are adjusted to the current timezone setting or to the given time zone. The effect of AT TIME ZONE also changes with the underlying data type. See:
Ignoring time zones altogether in Rails and PostgreSQL
If you extract a date from type timestamp [without time zone], you get the date for the current time zone. The day in the output will be the same as in the display of the timestamp value.
If you extract a date from type timestamp with time zone (timestamptz for short), the time zone offset is "applied" first. You still get the date for the current time zone, which agrees with the display of the timestamp. The same point in time translates to the next day in parts of Europe, when it is past 4 p.m. in California for instance. To get the date for a certain time zone, apply AT TIME ZONE first.
Therefore, what you describe at the top of the question contradicts your example.
Given that starts_at is a timestamp [without time zone] and the time on your server is set to the local time. Test with:
SELECT now();
Does it display the same time as a clock on your wall? If yes (and the db server is running with correct time), the timezone setting of your current session agrees with your local time zone. If no, you may want to visit the setting of timezone in your postgresql.conf or your client for the session. Details in the manual.
Be aware that the timezone offset used the opposite sign of what's displayed in timestamp literals. See:
Peculiar time zone handling in a Postgres database
To get your local date from starts_at just
SELECT starts_at::date
Tantamount to:
SELECT date(starts_at)
BTW, your local time is at UTC-7 right now, not UTC-8, because daylight savings time is in effect (not among the brighter ideas of the human race).
Pacific Standard TIME (PST) is normally 8 hours "earlier" (bigger timestamp value) than UTC (Universal Time Zone), but during daylight saving periods (like now) it can be 7 hours. That's why timestamptz is displayed as 2012-06-21 02:00:00-07 in your example. The construct AT TIME ZONE 'PST' takes daylight saving time into account. These two expressions yield different results (one in winter, one in summer) and may result in different dates when cast:
SELECT '2012-06-21 01:00:00'::timestamp AT TIME ZONE 'PST'
, '2012-12-21 01:00:00'::timestamp AT TIME ZONE 'PST'
I know this is an old one but You may want to consider using AT TIME ZONE "US/Pacific" when casting to avoid any PST/PDT issues. So
SELECT starts_at::TIMESTAMPTZ AT TIME ZONE "US/Pacific"
FROM schedules
WHERE ID = '40';