Representing a future time in PostgreSQL - postgresql

I’ve been conditioned to store past dates as UTC in a database since that is in fact when the event occurred. For future dates, I would store it with a specific timezone, to avoid changes such as leap seconds or timezone rule changes.
Postgres has timestamp with timezone, but under the covers, it stores it as UTC, inferring that the specified timezone is an offset of UTC. If the timezone rules were to change, that would not be reflected in the column.
What is recommended in this case?

Think [of it] like a calendar event. UTC doesn’t make sense for that
It sounds like you want to store a localtime with respect to a certain timezone.
In that case, store a timestamp (without timezone) and the timezone in a separate column.
For example, suppose you want to record an event which will occur at 10 am on Feb 26, 2030 in Chicago
and it must be at 10 am localtime regardless of the timezone rule in effect on that date.
If the database stores the timestamp without timezone:
unutbu=# select '2030-02-26 10:00:00'::timestamp as localtime, 'America/Chicago' AS tzone;
+---------------------+-----------------+
| localtime | tzone |
+---------------------+-----------------+
| 2030-02-26 10:00:00 | America/Chicago |
+---------------------+-----------------+
Then later, you can find the UTC datetime of the event using
unutbu=# select '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
| timezone |
+---------------------+
| 2030-02-26 16:00:00 |
+---------------------+
The query returns the UTC datetime, 2030-02-26 16:00:00, which corresponds to 2030-02-26 10:00:00 localtime in Chicago.
Using AT TIME ZONE delays the application of the timezone rules to when the query is made instead of when the timestamptz was inserted.
Using AT TIME ZONE on a timestamp localizes the datetime to the given timezone, but reports the datetime in the user's timezone.
Using AT TIME ZONE on a timestamptz converts the datetime to the given timezone, then drops the offset, thus returning a timestamp.
Above, AT TIME ZONE is used twice: first to localize a timestamp and next to convert the returned timestamptz to a new timezone (UTC). The result is a timestamp in UTC.
Here is an example, demonstrating AT TIME ZONE's behavior on timestamps:
unutbu=# SET timezone = 'America/Chicago';
unutbu=# SELECT '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago';
+------------------------+
| timezone |
+------------------------+
| 2030-02-26 10:00:00-06 |
+------------------------+
unutbu=# SET timezone = 'America/Los_Angeles';
unutbu=# SELECT '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago';
+------------------------+
| timezone |
+------------------------+
| 2030-02-26 08:00:00-08 |
+------------------------+
2030-02-26 10:00:00-06 and 2030-02-26 08:00:00-08 are the same datetimes but reported in different user timezones. This shows 10am in Chicago is 8am in Los Angeles (using current timezone definitions):
unutbu=# SELECT '2030-02-26 10:00:00-06'::timestamptz AT TIME ZONE 'America/Los_Angeles';
+---------------------+
| timezone |
+---------------------+
| 2030-02-26 08:00:00 |
+---------------------+
An alternative to using AT TIME ZONE twice is to set the user timezone to UTC. Then you could use
select localtime AT TIME ZONE tzone
Note that when done this way, a timestamptz is returned instead of a timestamp.
Beware that storing localtimes can be problematic because there can be nonexistent times and ambiguous times.
For example, 2018-03-11 02:30:00 is a nonexistent localtime in America/Chicago. Postgresql normalizes nonexistent localtimes by assuming it refers to the corresponding time after Daylight Savings Time (DST) has begun (as though someone forgot to set their clock forward):
unutbu=# select '2018-03-11 02:30:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
| timezone |
+---------------------+
| 2018-03-11 08:30:00 |
+---------------------+
(1 row)
unutbu=# select '2018-03-11 03:30:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
| timezone |
+---------------------+
| 2018-03-11 08:30:00 |
+---------------------+
(1 row)
An example of an ambiguous localtime is 2018-11-04 01:00:00 in America/Chicago. It occurs twice due to DST. Postgresql resolves this ambiguity by choosing the later time, after DST has ended:
unutbu=# select '2018-11-04 01:00:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
| timezone |
+---------------------+
| 2018-11-04 07:00:00 |
+---------------------+
Notice that this means there is no way to refer to 2018-11-04 06:00:00 UTC by storing localtimes in the America/Chicago timezone:
unutbu=# select '2018-11-04 00:59:59'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
| timezone |
+---------------------+
| 2018-11-04 05:59:59 |
+---------------------+

Particularly if you want to protect yourself from future time zune changes you should use timestamp with time zone.
PostgreSQL internally stores the number of microseconds since 2000-01-01 00:00:00, which is safe from time zone changes. If you keep updating your PostgreSQL, it will always display that absolute value correctly for your session time zone.
There is no provision for leap seconds in PostgreSQL.

For future dates, I would store it with a specific timezone, to avoid changes such as leap seconds or timezone rule changes.
That seems backward. The main advantage of UTC over other time zones is that it is less prone to unexpected future changes: UTC only introduces leap seconds at known, limited points of the calendar year; and has none of the frequent politically-mandated offset changes.
Storing values in some locally-managed timezone leaves those values more prone (compared with UTC) to arbitrary, unpredictable future changes in meaning.
So, the general recommendation is: Store all time values (whether date, or date+time) as UTC in the database, process them internally as UTC values; and convert to/from a local timezone only at external interfaces.
For PostgreSQL, that means prefer TIMESTAMP WITH TIME ZONE.

Related

Query Postgres Timestamp with Timezone wrong result

I have a table with a time column defined as
time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
my database and the server have the timezone UTC
Tue Apr 20 18:22:50 UTC 2021
When I ran the following query
SELECT id, time AT TIME ZONE 'utc' AS "TZ: UTC", time AT TIME ZONE 'Europe/Berlin' AS "TZ: Berlin" FROM orders ORDER BY id DESC;
results to
id | TZ: UTC | TZ: Berlin
-----+------------------------------+------------------------------
600 | 2021-04-20 18:18:07.11372+00 | 2021-04-20 16:18:07.11372+00
I would have expected in the TZ: Berlin column is
2021-04-20 20:18:07.11372+00.
When I run the query
SELECT id, time AT TIME ZONE 'utc' AS "TZ: UTC", time AT TIME ZONE 'UTC+2' AS "TZ: UTC+2" FROM orders ORDER BY id DESC
which results to the expected
id | TZ: UTC | TZ: UTC+2
-----+------------------------------+------------------------------
600 | 2021-04-20 18:18:07.11372+00 | 2021-04-20 20:18:07.11372+00
At this time of the year (summer) the timezones UTC+2 and Europe/Berlin are identical.
So what am I missing?
Kind regards
PS: The Version is
$ postgres -V postgres
postgres (PostgreSQL) 12.6
When I run
SELECT NOW() at time zone 'Europe/Berlin';
I get
timezone
----------------------------
2021-04-20 20:41:57.155641
Adding AT TIME ZONE to a timestamp without time zone merely adds the time zone to the timestamp. In your case, the time was stored as:
2021-04-20 18:18:07.11372
Adding the UTC time zone didn't change the hour portion of the time because it matches your session time zone.
Adding the Europe/Berlin time zone had the following effect:
2021-04-20 18:18:07.11372 = the time in Berlin, so we subtract two hours to get the time in UTC.
The case of UTC+2 is even more confusing. I suggest reading more about the posix time specifications.
Note this important bit:
The positive sign is used for zones west of Greenwich.
It worked as you expected, but for the wrong reason.
This might make it more clear:
SELECT t,
t at time zone 'UTC' as utc,
t at time zone 'Europe/Berlin' as berlin,
t at time zone 'UTC+2' as somewhere_west_of_utc,
t at time zone 'UTC-2' as berlinish
FROM (
VALUES ('2021-04-20T12:00:00'::timestamp)
) as v(t);
t | utc | berlin | somewhere_west_of_utc | berlinish
---------------------+------------------------+------------------------+------------------------+------------------------
2021-04-20 12:00:00 | 2021-04-20 12:00:00+00 | 2021-04-20 10:00:00+00 | 2021-04-20 14:00:00+00 | 2021-04-20 10:00:00+00
(1 row)
Again, I would strongly advise you to use timestamp with time zone where all the timestamps will be stored as UTC.
If you execute AT TIME ZONE on a timestamp without time zone, you get the absolute time when a clock in that time zone shows that time.
When a clock in Berlin shows 18:00, it is 16:00 UTC.

Why datetime without time zone foormatted as it have timezone?

I am experimenting with time zones.
My postgres table created as:
Table "public.xx"
Column | Type | Collation | Nullable | Default
--------+-----------------------------+-----------+----------+---------
dtz | timestamp with time zone | | |
dt | timestamp without time zone | | |
The server timezone is 'UTC'. I know this from show timezone;
Then I insert data:
insert into xx values( TIMESTAMP WITH TIME ZONE '2018-08-01 13:00:00+3', TIMESTAMP WITH TIME ZONE '2018-08-01 13:00:00+3' );
INSERT 0 1
tucha=> select * from xx;
dtz | dt
------------------------+---------------------
2018-08-01 10:00:00+00 | 2018-08-01 10:00:00
(1 row)
Results are easy to understand: the dates are stored in UTC thus 3 is subtracted.
Also notice that dtz have +00
Now when I use at time zone
tucha=> select dtz at time zone 'UTC', dt at time zone 'UTC' from xx;
timezone | timezone
---------------------+------------------------
2018-08-01 10:00:00 | 2018-08-01 10:00:00+00
(1 row)
The +00 is added for field which has no timezone and viceversa: no +00 for dtz field.
Why this happened?
a short answer is - because it is desined this way:
https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-ZONECONVERT
timestamp without time zone AT TIME ZONE zone returns timestamp
with time zone
timestamp with time zone AT TIME ZONE zone returns
timestamp without time zone
Longer:
as you said your client works in UTC timezone and server always stores timestamptz in UTC, thus select times match (you use UTC everywhere).
first select timestamptz is shown with +00 because this is timezone aware field - and it shows you the time zone. dt knows nothing of time zones, thus shows none...
Now when you use AT TIME ZONE you ask to show timestamps at SOME SPECIFIC time zone, thus time zone aware data type shows you the time for specific zone (adding hours and so), but after "moving" time it can't be reused as time zone aware (because it's not server UTC time anymore), thus it hides TZ. Opposite the time that was not aware of time zone, when displayed at some specific time zone, gains that "awareness" and deducting hours it shows +00 so you would know you operated on TZ not aware time stamp. I think that is the logic here.
I have found good article how to work with timezones (RU):
So – timestamp at time zone gives timestamptz which represents the moment in time when local time at given zone was as given.
and timestamptz at time zone gives timestamp, which shows what the time was in given timezone at given point in time.

Peculiar time zone handling in a Postgres database

My environment
I'm in Paris, France (UTC+1 or CET).
It's 12am (00:00), we're on the 25th of November 2016.
My Postgres database is hosted on Amazon Web Services (AWS RDS) in the eu-west-1 region.
The issue
Querying for the current_date (or current_time) with a specific time zone set seems to deliver results that aren't consistent with... my beliefs.
In particular, querying for the current_date yields a different result when using the CET time zone or the UTC+1 one.
Example
SET TIME ZONE 'UTC+01';
select current_date, current_time;
+------------+--------------------+
| date | timetz |
+------------+--------------------+
| 2016-11-24 | 22:00:01.581552-01 |
+---------------------------------+
Nope, that was yesterday -- two hours ago.
SET TIME ZONE 'CET';
select current_date, current_time;
or
SET TIME ZONE 'Europe/Paris';
select current_date, current_time;
+------------+--------------------+
| date | timetz |
+------------+--------------------+
| 2016-11-25 | 00:00:01.581552-01 |
+---------------------------------+
There's the correct time and date.
Question
What's going on there?
Is it too late for me and I mixed up UTC+1 and UTC-1 or is there something bigger that I'm overlooking?
Does AWS RDS have a role in this?
The issue seems unrelated to Amazon RDS: it has to do with the convention used by PostgreSQL. In this case, you do have the time zone name backwards. You mean 'UTC-01' where you write 'UTC+01'.
From the manual:
Another issue to keep in mind is that in POSIX time zone names,
positive offsets are used for locations west of Greenwich. Everywhere
else, PostgreSQL follows the ISO-8601 convention that positive
timezone offsets are east of Greenwich.
So time zone string used for SET TIME ZONE (and the display of SHOW timezone, accordingly) or the AT TIME ZONE construct use the opposite sign of what's displayed in timestamp (with time zone) literals! That's a very unfortunate disagreement between ISO and SQL standard on the one hand and POSIX on the other. (I think POSIX is to blame.) See:
Oddities with AT TIME ZONE and UTC offsets
Why does PostgreSQL interpret numeric UTC offset as POSIX and not ISO-8601?
But 'CET' or 'UTC-01' are both still potentially wrong for Paris because they are not taking rules for daylight saving time into account.
(DST is one of the most moronic concepts in the history of mankind.)
Paris (like most of Europe) uses CET during winter and CEST during summer. Your tests with 'CET' just happen to work in November. If you try the same in the summer time, you get the wrong result.
To be on the safe side, always use the time zone name 'Europe/Paris', which considers DST rules. The call is more expensive.
The function current_time takes DST rules into account if your time zone setting implies any. But 'UTC-01' is a plain time offset. I never use the data type time with time zone or current_time to begin with. The manual once more:
We do not recommend using the type time with time zone (though it is
supported by PostgreSQL for legacy applications and for compliance
with the SQL standard)
Consider:
SELECT '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'UTC+01' AS plus_wrong
, '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'UTC-01' AS minus_right
plus_wrong | minus_right
---------------------+---------------------
2016-06-05 23:00:00 | 2016-06-06 01:00:00
SELECT '2016-01-01 00:00+0'::timestamptz AT TIME ZONE 'CET' AS cet_winter
, '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'CEST' AS cest_summer
, '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'CET' AS cet_no_dst -- CET wrong!
cet_winter | cest_summer | cet_no_dst
---------------------+---------------------+---------------------
2016-01-01 01:00:00 | 2016-06-06 02:00:00 | 2016-06-06 01:00:00 -- wrong
SELECT '2016-06-06 00:00+0'::timestamptz AT TIME ZONE 'Europe/Paris' AS paris_summer
, '2016-01-01 00:00+0'::timestamptz AT TIME ZONE 'Europe/Paris' AS paris_winter
paris_summer | paris_winter
----------------------+----------------------
2016-06-06 02:00:00 | 2016-01-01 01:00:00 -- always right
Related:
Ignoring time zones altogether in Rails and PostgreSQL
Time zone names with identical properties yield different result when applied to timestamp
Time zone storage in data type "timestamp with time zone"

Converting timestamp to timestamp in a specific time zone in Postgres

I have a table that has a column whose data type is timestamp without time zone , I'm trying to convert it to timestamp without time zone at a given time zone.
These are my Postgres 9.3 settings
select current_setting('TIMEZONE');
current_setting
-----------------
Hongkong
select * from pg_timezone_names where name = 'Hongkong';
name | abbrev | utc_offset | is_dst
----------+--------+------------+--------
Hongkong | HKT | 08:00:00 | f
Here is what I did to convert it to HKT:
-- this SQL gives me what I expected
select '2015-01-05 12:00:00'::timestamp without time zone
at time zone 'UTC'
at time zone 'HKT';
---------------------
2015-01-05 20:00:00
-- Shouldn't this produce the same result with the above one?
-- How do I make this work?
-- Don't tell me to change it to UTC-08:00 ...
select '2015-01-05 12:00:00'::timestamp without time zone
at time zone 'UTC'
at time zone 'UTC+08:00';
---------------------
2015-01-05 04:00:00 -- WHY?
The reason behind this is why you really shouldn't use time-zone offsets in PostgreSQL (unless you are know exactly what you do).
The time zone 'UTC+08:00' is a POSIX-style time zone specification, 'Hongkong' is the exact time zone name, and 'HKT' is (one of) its abbreviation(s).
The pg_timezone_names system view's utc_offset column is defined to be the Offset from UTC (positive means east of Greenwich).
But in the POSIX-style time zone specification, the offset part is different:
... Another issue to keep in mind is that in POSIX time zone names, positive offsets are used for locations west of Greenwich. Everywhere else, PostgreSQL follows the ISO-8601 convention that positive timezone offsets are east of Greenwich.
So, instead of using offsets (as intervals), or POSIX-style time zone specifications, you should use:
Time zone abbreviations, if you want to deal with daylight saving rules on your own,
Exact time zone names, everywhere else (preferred).
In short, this is the difference between abbreviations and full names: abbreviations represent a specific offset from UTC, whereas many of the full names imply a local daylight-savings time rule, and so have two possible UTC offsets.
To complicate matters, some jurisdictions have used the same timezone abbreviation to mean different UTC offsets at different times; for example, in Moscow MSK has meant UTC+3 in some years and UTC+4 in others. PostgreSQL interprets such abbreviations according to whatever they meant (or had most recently meant) on the specified date; but, as with the EST example above, this is not necessarily the same as local civil time on that date.
But the most simple solution is to use timestamp with time zone: you already set your TimeZone setting to 'Hongkong', so timestamp with time zone values will be displayed in that time zone to your (PostgreSQL) client.
set time zone 'Hongkong';
select current_setting('TimeZone') TimeZone,
dt original,
dt AT TIME ZONE 'UTC' AT TIME ZONE 'UTC+08:00' "UTC+08:00",
dt AT TIME ZONE 'UTC' AT TIME ZONE 'UTC+8' "UTC+8",
dt AT TIME ZONE 'UTC' AT TIME ZONE 'UTC-8' "UTC-8",
dt AT TIME ZONE 'UTC' AT TIME ZONE INTERVAL '+08:00' "INTERVAL +08:00",
dt AT TIME ZONE 'UTC' AT TIME ZONE 'HKT' "HKT",
dt AT TIME ZONE 'UTC' AT TIME ZONE 'Hongkong' "Hongkong",
dt AT TIME ZONE 'UTC' "with time zone"
from (values (timestamp '2015-01-05 12:00:00')) v(dt);
-- TIMEZONE | ORIGINAL | UTC+08:00
-- ---------+---------------------+--------------------
-- Hongkong | 2015-01-05 12:00:00 | 2015-01-05 04:00:00
-- UTC+8 | UTC-8 | INTERVAL +08:00
-- --------------------+---------------------+--------------------
-- 2015-01-05 04:00:00 | 2015-01-05 20:00:00 | 2015-01-05 20:00:00
-- HKT | HONGKONG | WITH TIME ZONE
-- --------------------+---------------------+-----------------------
-- 2015-01-05 20:00:00 | 2015-01-05 20:00:00 | 2015-01-05 20:00:00+08
SQLFiddle

Postgresql: how to correctly create timestamp with timezone from timestamp, timezone fields

I have a table with a timestamp without time zone.
YYYY-MM-DD HH:MM:SS
and a field "timezone" that is either "P" for Pacific or "M" for Mountain.
I need to create a field of type "timestamp with time zone"
Given the two fields I have, is there a way to do this that correctly accounts for Daylight Saving Time?
Specifically:
timestamp: 2013-11-03 01:00:00
timezone: "P"
would become: 2013-11-03 01:00:00-07
and
timestamp: 2013-11-03 03:00:00
timezone: "P"
would become: 2013-11-03 03:00:00-08
The difference between TIMESTAMP WITHOUT TIME ZONE and TIMESTAMP WITH TIME ZONE (TIMESTAMPTZ) can be quite tricky to understand if you consider their names. (In fact, the specifications seem to be sufficiently confusing so that various RDBMS implement it in a different way.)
In PostgreSQL, neither types store the time zone of the value when it was stored, but TIMESTAMPTZ stores the value as a precise instant in time based on the UTC reference, whereas TIMESTAMP WITHOUT TIME ZONE is always relative.
When queried, a TIMESTAMPTZ will be adjusted to represent the same instant in time as initially stored (in whichever part of the world this was) as the instant it would be in the current time zone as configured by the client.
A TIMESTAMP WITHOUT TIME ZONE will always be the same value relative to the time zone configured by the client, even if the time zone where you query it from differs: the instant represented by 2013-11-03 03:00:00 will be ambiguous and depend on the client settings.
Presumably, you used your "timezone" column (P or M) with your TIMESTAMP WITHOUT TIME ZONE to compensate for the ambiguity in the input value.
In principle, if you are in the same relative time zone as the one where you stored the timestamp, you should get the same value back, so if you've set your client in the US/Pacific time zone and if you've stored 2013-11-03 03:00:00 in your P time zone, you should get 2013-11-03 03:00:00 back. However, this is only valid when there is no ambiguity in the relative value.
The problem here in your first example is that there already is some ambiguity:
timestamp: 2013-11-03 01:00:00 timezone: "P" would become: 2013-11-03
01:00:00-07
2013-11-03 01:00:00 can represent two distinct instants in time in the US/Pacific time zone, so with just 2013-11-03 01:00:00 and "P", you've already lost information that you won't be able to recover.
If you just wanted it to change between '-08' and '-07' depending on the DST setting at that instant in time, this would have been done for you automatically, but you should have use a TIMESTAMPTZ in the first place, to be precise on which instant in time you were representing.
Here is an example where the initial time zone is kept, so you can see the change between '-08' and '-07':
SET time zone 'US/Pacific';
SELECT t AS "Date/Time for US/Pacific",
t AT time zone 'UTC' "Date/Time in UTC"
FROM (VALUES
('2013-11-03 00:00:00-07'::timestamptz),
('2013-11-03 01:00:00-07'::timestamptz),
('2013-11-03 02:00:00-07'::timestamptz),
('2013-11-03 03:00:00-07'::timestamptz)) AS v(t);
Results:
| DATE/TIME FOR US/PACIFIC | DATE/TIME IN UTC |
|--------------------------|---------------------|
| 2013-11-03 00:00:00-07 | 2013-11-03 07:00:00 |
| 2013-11-03 01:00:00-07 | 2013-11-03 08:00:00 |
| 2013-11-03 01:00:00-08 | 2013-11-03 09:00:00 |
| 2013-11-03 02:00:00-08 | 2013-11-03 10:00:00 |
Unfortunately, there is no way to handle DST change with just your two fields.
It's certainly worth reading the Date/Time types section of the PostgreSQL manual, as well as paying attention to the "return types" column of the table in the AT TIME ZONE documentation for a better understanding of these problems.
First, when saying that the result would become for example 2013-11-03 01:00:00-07, it should be added that this actually depends on the time zone setting of the SQL client. For instance a session in european time will never read 2013-11-03 01:00:00-07 as the value of a timestamp with time zone because no european country is ever at GMT-07.
That said, the conversion can be done with the AT TIME ZONE construct applied to a timestamp without time zone.
Assuming we run this from the US/Pacific time zone:
SET time zone 'US/Pacific';
SELECT t AT TIME ZONE
case z when 'P' then 'US/Pacific' when 'M' then 'US/Mountain' end
from (values
('2013-11-03 01:00:00'::timestamp, 'P'),
('2013-11-03 03:00:00'::timestamp, 'P')
) as v(t,z);
The result is:
timezone
------------------------
2013-11-03 01:00:00-08
2013-11-03 03:00:00-08
2013-11-03 01:00:00 AT time zone 'US/Pacific' has an ambiguity because it belongs to the hour span which happens first in the -07 timezone, and then a second time in the -08 timezone after the DST switch. The interpretation of postgres is to see it in the -08 timezone. If we consider the minute before, it falls into the -07 timezone.
Check if this makes any sense to you
set timezone to 'PST8PDT';
select now();
now
-------------------------------
2013-09-28 03:24:20.169189-07
select ts,
ts at time zone 'PST' as "PST",
ts at time zone 'PDT' as "PDT"
from (values
('2013-11-03 01:00:00'::timestamp),
('2013-11-03 02:00:00'),
('2013-11-03 03:00:00')
) s (ts)
;
ts | PST | PDT
---------------------+------------------------+------------------------
2013-11-03 01:00:00 | 2013-11-03 01:00:00-08 | 2013-11-03 01:00:00-07
2013-11-03 02:00:00 | 2013-11-03 02:00:00-08 | 2013-11-03 01:00:00-08
2013-11-03 03:00:00 | 2013-11-03 03:00:00-08 | 2013-11-03 02:00:00-08