The current time in Shanghai is 2024-03-19 00:43
show timezone
+----------+
| TimeZone |
|----------|
| GMT |
+----------+
SELECT CURRENT_DATE AT TIME ZONE 'Asia/Shanghai', CURRENT_TIME AT TIME ZONE 'Asia/Shanghai', CURRENT_TIMESTAMP AT TIME ZONE 'Asia/Shanghai';
+---------------------+-----------------------+---------------------------+
| timezone | timezone | timezone |
|---------------------+-----------------------+---------------------------|
| 2024-03-18 08:00:00 | 00:43:52.916370+08:00 | 2024-03-19 00:43:52.91637 |
+---------------------+-----------------------+---------------------------+
- Why the date of CURRENT_TIMESTAMP is different from CURRENT_DATE in Postgres?
- How can I get the current date in Shanghai for the result ‘2024-03-19’ if the time zone is GMT?
2
Answers
The similar sounding expressions
CURRENT_DATE
andCURRENT_TIMESTAMP
are very different in nature.CURRENT_TIMESTAMP
returns data typetimestamptz
(timestamp with time zone
), and does not depend on local settings. (Only the display does.) When you apply theAT TIME ZONE
construct you produce the corresponding localtimestamp
(timestamp without time zone
) for the given time zone. Still the same point in universal time.CURRENT_DATE
returns data typedate
, and depends on the currenttimezone
setting of the session. It’s the local timestamp truncated to the date. This truncation introduces the difference, the quantity depends on the currenttimezone
setting. When applying theAT TIME ZONE
construct,date
is coerced back totimestamp
(materializing the difference accrued by truncating earlier – it’s now a different point in universal time!) before generating the matchingtimestamptz
.And
CURRENT_TIME
returns the questionable typetimetz
(time with time zone
). This function, as well as the data type are included in the SQL standard, but discouraged in Postgres (or generally, really). The concept of just time with time zone is inherently ambiguous. Think of daylight saving time or historical shifts. I never usetimetz
. (So also notCURRENT_TIME
.)Related:
Consider the demo:
As already established,
date
type doesn’t support time zones. If you cast it totimestamp
which does support time zones, you’ll get midnight on that date. Switching between these is sufficient for points in time.But if you want true dates, you might be interested in
timestamptz
-based range typetstzrange
. It can describe the actual period between two points in time that makes up a specific date. Equipped with that, you can see from GMT what Shanghai would consider the same date:To see if
A
happened on the same date asB
, extracting the date part from each of these would get you the wrong answer; local dates are shifted compared to each other. Meanwhile, thetstzrange
is specific and absolute, and@>
operator tells you if the point is in the range: demoNote how the range excludes the upper bound with
)
: it spans up to the midnight of the following date, but doesn’t include it. It’s more elegant than making23:59:59.999999
the upper bound, and including it with]
.