PostgreSQL內建支援智慧式日期時間輸入格式。日期及時間以字串格式輸入,以預先定義的方式,分隔為多個欄位。每一個欄位可能會被解譯為數字、忽視或拒絕。處理程式也內建常見的描述字,如月份、星期及時區名稱。
本文件說明日期及時間解譯的方法和步驟,也包含了常見描述字的列表。
由於時區縮寫並沒有很好地標準化,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/ 中的檔案,則由您來進行備份 - 正常的資料庫轉存將不包含此目錄。
Table B.1. 月份名稱
月份 | 縮寫 |
---|---|
Table B.2. 星期名稱
星期 | 縮寫 |
---|---|
Table B.3. 日期/時間修飾字
修飾字 | 說明 |
---|---|
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
日期時間資料將會以下列流程解譯:(分隔符號均為半型文字)
以分隔符號將其分解為多個段落,如字串、時區或數字。
如果是以冒號(:)分隔的數字格式,那麼這是一個時間的字串,其所包括的內容都是時間資訊的一部份。
如果是以連字號(-)、斜線(/)、或兩個以上的間隔號(.)所分隔的數字格式,那麼這是一個日期的字串,它可能包含文字型式的月份名稱。但如果日期分隔符號已經先出現了,那麼它將被解釋為時區資訊(例如: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年)。
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.
However, every year divisible by 100 is not a leap year.
However, every year divisible by 400 is a leap year after all.