Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
PostgreSQL 內建支援智慧式日期時間輸入格式。日期及時間以字串格式輸入,以預先定義的方式,分隔為多個欄位。每一個欄位可能會被解譯為數字、忽視或拒絕。處理程式也內建常見的描述字,如月份、星期及時區名稱。
本文件說明日期及時間解譯的方法和步驟,也包含了常見描述字的列表。
The Julian Date system is a method for numbering days. It is unrelated to the Julian calendar, though it is confusingly named similarly to that calendar. The Julian Date system was invented by the French scholar Joseph Justus Scaliger (1540–1609) and probably takes its name from Scaliger's father, the Italian scholar Julius Caesar Scaliger (1484–1558).
In the Julian Date system, each day has a sequential number, starting from JD 0 (which is sometimes called the Julian Date). JD 0 corresponds to 1 January 4713 BC in the Julian calendar, or 24 November 4714 BC in the Gregorian calendar. Julian Date counting is most often used by astronomers for labeling their nightly observations, and therefore a date runs from noon UTC to the next noon UTC, rather than from midnight to midnight: JD 0 designates the 24 hours from noon UTC on 24 November 4714 BC to noon UTC on 25 November 4714 BC.
Although PostgreSQL supports Julian Date notation for input and output of dates (and also uses Julian dates for some internal datetime calculations), it does not observe the nicety of having dates run from noon to noon. PostgreSQL treats a Julian Date as running from local midnight to local midnight, the same as a normal date.
This definition does, however, provide a way to obtain the astronomical definition when you need it: do the arithmetic in time zone UTC+12
. For example,
The SQL standard states that“Within the definition of a‘datetime literal’, the‘datetime values’are constrained by the natural rules for dates and times according to the Gregorian calendar”.PostgreSQLfollows the SQL standard's lead by counting dates exclusively in the Gregorian calendar, even for years before that calendar was in use. This rule is known as the_proleptic Gregorian calendar_.
The Julian calendar was introduced by Julius Caesar in 45 BC. It was in common use in the Western world until the year 1582, when countries started changing to the Gregorian calendar. In the Julian calendar, the tropical year is approximated as 365 1/4 days = 365.25 days. This gives an error of about 1 day in 128 years.
The accumulating calendar error prompted Pope Gregory XIII to reform the calendar in accordance with instructions from the Council of Trent. In the Gregorian calendar, the tropical year is approximated as 365 + 97 / 400 days = 365.2425 days. Thus it takes approximately 3300 years for the tropical year to shift one day with respect to the Gregorian calendar.
The approximation 365+97/400 is achieved by having 97 leap years every 400 years, using the following rules:
Every year divisible by 4 is a leap year. |
---|
So, 1700, 1800, 1900, 2100, and 2200 are not leap years. But 1600, 2000, and 2400 are leap years. By contrast, in the older Julian calendar all years divisible by 4 are leap years.
The papal bull of February 1582 decreed that 10 days should be dropped from October 1582 so that 15 October should follow immediately after 4 October. This was observed in Italy, Poland, Portugal, and Spain. Other Catholic countries followed shortly after, but Protestant countries were reluctant to change, and the Greek Orthodox countries didn't change until the start of the 20th century. The reform was observed by Great Britain and its dominions (including what is now the USA) in 1752. Thus 2 September 1752 was followed by 14 September 1752. This is why Unix systems have thecal
program produce the following:
But, of course, this calendar is only valid for Great Britain and dominions, not other places. Since it would be difficult and confusing to try to track the actual calendars that were in use in various places at various times,PostgreSQLdoes not try, but rather follows the Gregorian calendar rules for all dates, even though this method is not historically accurate.
Different calendars have been developed in various parts of the world, many predating the Gregorian system. For example, the beginnings of the Chinese calendar can be traced back to the 14th century BC. Legend has it that the Emperor Huangdi invented that calendar in 2637 BC. The People's Republic of China uses the Gregorian calendar for civil purposes. The Chinese calendar is used for determining festivals.
The_Julian Date_system is another type of calendar, unrelated to the Julian calendar though it is confusingly named similarly to that calendar. The Julian Date system was invented by the French scholar Joseph Justus Scaliger (1540-1609) and probably takes its name from Scaliger's father, the Italian scholar Julius Caesar Scaliger (1484-1558). In the Julian Date system, each day has a sequential number, starting from JD 0 (which is sometimes called_the_Julian Date). JD 0 corresponds to 1 January 4713 BC in the Julian calendar, or 24 November 4714 BC in the Gregorian calendar. Julian Date counting is most often used by astronomers for labeling their nightly observations, and therefore a date runs from noon UTC to the next noon UTC, rather than from midnight to midnight: JD 0 designates the 24 hours from noon UTC on 24 November 4714 BC to noon UTC on 25 November 4714 BC.
AlthoughPostgreSQLsupports Julian Date notation for input and output of dates (and also uses Julian dates for some internal datetime calculations), it does not observe the nicety of having dates run from noon to noon.PostgreSQLtreats a Julian Date as running from midnight to midnight.
PostgreSQL can accept time zone specifications that are written according to the POSIX standard's rules for the TZ
environment variable. POSIX time zone specifications are inadequate to deal with the complexity of real-world time zone history, but there are sometimes reasons to use them.
A POSIX time zone specification has the form
(For readability, we show spaces between the fields, but spaces should not be used in practice.) The fields are:
STD
is the zone abbreviation to be used for standard time.
offset
is the zone's standard-time offset from UTC.
DST
is the zone abbreviation to be used for daylight-savings time. If this field and the following ones are omitted, the zone uses a fixed UTC offset with no daylight-savings rule.
dstoffset
is the daylight-savings offset from UTC. This field is typically omitted, since it defaults to one hour less than the standard-time offset
, which is usually the right thing.
rule
defines the rule for when daylight savings is in effect, as described below.
In this syntax, a zone abbreviation can be a string of letters, such as EST
, or an arbitrary string surrounded by angle brackets, such as <UTC-05>
. Note that the zone abbreviations given here are only used for output, and even then only in some timestamp output formats. The zone abbreviations recognized in timestamp input are determined as explained in .
The offset fields specify the hours, and optionally minutes and seconds, difference from UTC. They have the format hh
[:
mm
[:
ss
]] optionally with a leading sign (+
or -
). The positive sign is used for zones west of Greenwich. (Note that this is the opposite of the ISO-8601 sign convention used elsewhere in PostgreSQL.) hh
can have one or two digits; mm
and ss
(if used) must have two.
The daylight-savings transition rule
has the format
(As before, spaces should not be included in practice.) The dstdate
and dsttime
fields define when daylight-savings time starts, while stddate
and stdtime
define when standard time starts. (In some cases, notably in zones south of the equator, the former might be later in the year than the latter.) The date fields have one of these formats:
n
A plain integer denotes a day of the year, counting from zero to 364, or to 365 in leap years.
J
n
In this form, n
counts from 1 to 365, and February 29 is not counted even if it is present. (Thus, a transition occurring on February 29 could not be specified this way. However, days after February have the same numbers whether it's a leap year or not, so that this form is usually more useful than the plain-integer form for transitions on fixed dates.)
M
m
.
n
.
d
This form specifies a transition that always happens during the same month and on the same day of the week. m
identifies the month, from 1 to 12. n
specifies the n
'th occurrence of the weekday identified by d
. n
is a number between 1 and 4, or 5 meaning the last occurrence of that weekday in the month (which could be the fourth or the fifth). d
is a number between 0 and 6, with 0 indicating Sunday. For example, M3.2.0
means “the second Sunday in March”.
The M
format is sufficient to describe many common daylight-savings transition laws. But note that none of these variants can deal with daylight-savings law changes, so in practice the historical data stored for named time zones (in the IANA time zone database) is necessary to interpret past time stamps correctly.
The time fields in a transition rule have the same format as the offset fields described previously, except that they cannot contain signs. They define the current local time at which the change to the other time occurs. If omitted, they default to 02:00:00
.
If a daylight-savings abbreviation is given but the transition rule
field is omitted, the fallback behavior is to use the rule M3.2.0,M11.1.0
, which corresponds to USA practice as of 2020 (that is, spring forward on the second Sunday of March, fall back on the first Sunday of November, both transitions occurring at 2AM prevailing time). Note that this rule does not give correct USA transition dates for years before 2007.
As an example, CET-1CEST,M3.5.0,M10.5.0/3
describes current (as of 2020) timekeeping practice in Paris. This specification says that standard time has the abbreviation CET
and is one hour ahead (east) of UTC; daylight savings time has the abbreviation CEST
and is implicitly two hours ahead of UTC; daylight savings time begins on the last Sunday in March at 2AM CET and ends on the last Sunday in October at 3AM CEST.
The four timezone names EST5EDT
, CST6CDT
, MST7MDT
, and PST8PDT
look like they are POSIX zone specifications. However, they actually are treated as named time zones because (for historical reasons) there are files by those names in the IANA time zone database. The practical implication of this is that these zone names will produce valid historical USA daylight-savings transitions, even when a plain POSIX specification would not.
One should be wary that it is easy to misspell a POSIX-style time zone specification, since there is no check on the reasonableness of the zone abbreviation(s). For example, SET TIMEZONE TO FOOBAR0
will work, leaving the system effectively using a rather peculiar abbreviation for UTC.
修飾字 | 說明 |
---|---|
January
Jan
February
Feb
March
Mar
April
Apr
May
June
Jun
July
Jul
August
Aug
September
Sep, Sept
October
Oct
November
Nov
December
Dec
Sunday
Sun
Monday
Mon
Tuesday
Tue, Tues
Wednesday
Wed, Weds
Thursday
Thu, Thur, Thurs
Friday
Fri
Saturday
Sat
AM
12:00 之前的時間
AT
忽略
JULIAN
,JD
,J
接下來的字串是 Julian Date 格式
ON
忽略
PM
12:00 之後的時間
T
接下來的字串是 time
However, every year divisible by 100 is not a leap year. |
However, every year divisible by 400 is a leap year after all. |
日期時間資料將會以下列流程解譯:(分隔符號均為半型文字)
以分隔符號將其分解為多個段落,如字串、時區或數字。
如果是以冒號(:)分隔的數字格式,那麼這是一個時間的字串,其所包括的內容都是時間資訊的一部份。
如果是以連字號(-)、斜線(/)、或兩個以上的間隔號(.)所分隔的數字格式,那麼這是一個日期的字串,它可能包含文字型式的月份名稱。但如果日期分隔符號已經先出現了,那麼它將被解釋為時區資訊(例如:Asia/Taipei)。
如果整個字串都是數字所組成,那麼它可能是符合ISO 8601格式的日期(例如:19990113,表示西元1999年1月3日),或時間(例如:141516,表示14:15:16)。
如果它是以加號(+)或減號(-)開頭的話,那麼它是一個數字型態的時區資訊或是特別的區間。
如果是一個字串,進行下列比對規則:
以 binary-search 表格,尋找時區的表示字。
如果沒有找到的話,則搜尋慣用字(如:today),星期(如:Thursday),月份(如:January),或介系詞(如:at, on)。
如果都沒有找到,就回傳錯誤訊息。
如果是一個由數字組成的字串,則進行下列判斷:
如果是 8 個或 6 個數字,而先前也沒有讀到其他日期的資訊,那麼它會被解譯為一個數字型態的日期(如:19990118 或 990118),對應年月日格式為 YYYYMMDD 或 YYMMDD。
如果是 3 位數字,而且先前已處理到年份資訊的話,那麼它會被解譯為該年的第幾天。
如果是 4 位或 6 位數字,而且先前已處理到年份資訊的話,那麼它會被解譯為時間資訊,對應格式為 HHMM 或 HHMMSS。
如果是 3 個或更多的數字,並且先前未處理到日期資訊的話,那麼它會是年份資訊。(這里將直接判斷為 yy-mm-dd 的日期格式。)
最後,日期格式將依 DateStyle 所定義的,設定為:mm-dd-yy,dd-mm-yy,或yy-mm-dd。其中如果月份或日子名稱無法找到合法字詞的話,那將會回傳錯誤的訊息。
如果指定了 BC(西元前)的話,那麼實際儲存值將是負的年份數再加1。(陽曆 Gregorian year 中並無西元 0 年,所以西元 1 年,以數值 0 作為年份的記錄值。)
沒有指定 BC 的 2 位數年份,將自動被調整為4位數。其規則為:若小於 70,則加 2000 作為其記錄值,否則就加 1900 作為記錄值。
若需要描述西元(Gregorian years AD) 1-99 年,請將年份數值以 0補滿 4 位數(例如:0099 表示西元 99 年)
Ordinarily, if a date/time string is syntactically valid but contains out-of-range field values, an error will be thrown. For example, input specifying the 31st of February will be rejected.
During a daylight-savings-time transition, it is possible for a seemingly valid timestamp string to represent a nonexistent or ambiguous timestamp. Such cases are not rejected; the ambiguity is resolved by determining which UTC offset to apply. For example, supposing that the TimeZone parameter is set to America/New_York
, consider
Because that day was a spring-forward transition date in that time zone, there was no civil time instant 2:30AM; clocks jumped forward from 2AM EST to 3AM EDT. PostgreSQL interprets the given time as if it were standard time (UTC-5), which then renders as 3:30AM EDT (UTC-4).
Conversely, consider the behavior during a fall-back transition:
On that date, there were two possible interpretations of 1:30AM; there was 1:30AM EDT, and then an hour later after clocks jumped back from 2AM EDT to 1AM EST, there was 1:30AM EST. Again, PostgreSQL interprets the given time as if it were standard time (UTC-5). We can force the other interpretation by specifying daylight-savings time:
The precise rule that is applied in such cases is that an invalid timestamp that appears to fall within a jump-forward daylight savings transition is assigned the UTC offset that prevailed in the time zone just before the transition, while an ambiguous timestamp that could fall on either side of a jump-back transition is assigned the UTC offset that prevailed just after the transition. In most time zones this is equivalent to saying that “the standard-time interpretation is preferred when in doubt”.
In all cases, the UTC offset associated with a timestamp can be specified explicitly, using either a numeric UTC offset or a time zone abbreviation that corresponds to a fixed UTC offset. The rule just given applies only when it is necessary to infer a UTC offset for a time zone in which the offset varies.
由於時區縮寫並沒有很好地標準化,PostgreSQL 提供了一種自訂的伺服器接受的縮寫集方法。timezone_abbreviations 運行時參數決定有效的縮寫集。雖然此參數可由任何資料庫使用者變更,但其可能的值受資料庫管理員控制 - 實際上它們是儲存在安裝目錄的 .../share/timezonesets/ 中的組態檔案的名稱。透過增加或變更該目錄中的檔案,管理員可以為時區縮寫設定本地策略。
timezone_abbreviations 可以設定為在 .../share/timezonesets/ 中找到的任何檔案名稱,檔案的名稱需要完全是英文字母的。(禁止 timezone_abbreviations 中的非英文字母字元可以防止讀取目標目錄之外的檔案,以及讀取編輯器備份檔案和其他無關檔案。)
時區縮寫檔案可以包含空白行和以 # 開頭的註釋。非註釋行必須具有以下格式之一:
zone_abbreviation 只是定義的縮寫。offset 是一個整數,定義與 UTC 相等的偏移量,以秒為單位,正向格林威治為東,負向為西。例如,-18000 將在格林威治以西 5 小時或北美東海岸標準時間。D 的區域名稱表示本地夏令時間而不是標準時間。
或者,可以定義 time_zone_name,引用 IANA 時區資料庫中定義的區域名稱。查詢區域的定義以查看該區域中是否正在使用縮寫,如果是,則使用適當的含義 - 即,目前正在確定其值的時間戳記中使用的含義,或者如果當時不是目前使用的話,則使用之前的含義,如果僅在該時間之後使用,則使用最舊的含義。這種行為對於處理其含義歷史變化的縮寫至關重要。還允許根據區域名稱定義縮寫,其中不出現該縮寫;使用縮寫就等於寫出區域名稱。
在定義與 UTC 的偏移量從未改變的縮寫時,偏好使用簡單的整數偏移量,因為這些縮寫比需要查閱時區定義的縮寫要簡單得多。
@INCLUDE 語法允許在 .../share/timezonesets/ 目錄中包含另一個檔案。包含可以嵌套到某個有限的深度。
@OVERRIDE 語法指示檔案中的後續項目可以覆蓋先前的項目(通常是從包含的檔案中獲取的項目)。如果沒有這個,相同時區縮寫的衝突定義將被視為錯誤。
在未修改的安裝環境中,檔案 Default 包含了世界上大多數地區的所有非衝突時區縮寫。為這些區域提供了澳大利亞和印度的附加檔案:這些檔案先有預設設定,然後根據需要增加或修改縮寫。
出於參考目的,標準安裝還包含 Africa.txt,America.txt 等文件,其中包含有關根據 IANA 時區資料庫已知正在使用的每個時區縮寫的訊息。可以根據需要將這些檔案中找到的區域名稱定義複製並貼到自行定義配置檔案中。請注意,由於名稱中包含了點,因此無法將這些檔案直接引用為 timezone_abbreviations 設定。
如果在讀取時區縮寫集時發生錯誤,則不會應用新值並保留舊值。如果在啟動資料庫時發生錯誤,則啟動失敗。
配置檔案中定義的時區縮寫會覆寫 PostgreSQL 中內建的非時區定義。例如,澳大利亞配置檔案定義了 SAT(南澳大利亞標準時間)。當此檔案有效時,SAT 將不會被識別為星期六的縮寫。
如果您修改 .../share/timezonesets/ 中的檔案,則由您來進行備份 - 正常的資料庫轉存將不包含此目錄。