ชนิดข้อมูลเป็นชื่อสั้นtimestamp
ๆ
ตัวเลือกอื่น ๆสั้นสำหรับtimestamp without time zone
timestamptz
timestamp with time zone
timestamptz
เป็นประเภทที่ต้องการในตระกูลวันที่ / เวลาแท้จริง ได้typispreferred
ตั้งค่าไว้ในpg_type
ซึ่งสามารถเกี่ยวข้อง:
ที่เก็บข้อมูลภายในและยุค
ภายในเวลาประทับมีพื้นที่เก็บข้อมูล8 ไบต์บนดิสก์และใน RAM เป็นค่าจำนวนเต็มที่แทนจำนวน microseconds จาก Postgres epoch, 2000-01-01 00:00:00 UTC
Postgres ยังมีในตัวของความรู้ที่ใช้กันทั่วไปUNIX เวลาวินาทีนับจากยุคยูนิกซ์ 1970/01/01 00:00:00 UTC และการใช้ฟังก์ชั่นว่าในหรือto_timestamp(double precision)
EXTRACT(EPOCH FROM timestamptz)
รหัสแหล่งที่มา:
* Timestamps รวมถึงช่วงเวลา h / m / s ถูกเก็บไว้เป็น
* ค่า int64 พร้อมหน่วยไมโครวินาที กาลครั้งหนึ่งนานมาแล้ว
* ค่าสองเท่าของหน่วยวินาที)
และ:
/ * Julian-date เทียบเท่ากับวันที่ 0 ใน Unix และ Postgres การคำนวณ * /
#define UNIX_EPOCH_JDATE 2440588 / * == date2j (1970, 1, 1) * /
#define POSTGRES_EPOCH_JDATE 2451545 / * == date2j (2000, 1, 1) * /
ความละเอียดไมโครวินาทีแปลได้สูงสุด 6 หลักสำหรับเศษเสี้ยววินาที
timestamp
ค่าที่พิมพ์ตามที่บอก Postgres ว่าไม่มีการระบุเขตเวลาอย่างชัดเจน เขตเวลาปัจจุบันจะถือว่า Postgres ละเว้นตัวปรับเปลี่ยนเขตเวลาที่เพิ่มโดยไม่ได้ตั้งใจtimestamp
[without time zone]
ไม่มีการเลื่อนชั่วโมงสำหรับการแสดงผล ด้วยการตั้งค่าเขตเวลาเดียวกันทั้งหมดจึงเป็นเรื่องปกติ สำหรับเขตเวลาที่แตกต่างกันการตั้งค่าความหมายเปลี่ยนแปลง แต่ค่าและการแสดงผลยังคงเหมือนเดิม
timestamptz
การจัดการที่timestamp with time zone
แตกต่างกันอย่างละเอียด ฉันพูดคู่มือที่นี่ :
สำหรับtimestamp with time zone
ค่าที่เก็บไว้ภายในจะเป็นUTC เสมอ ( เวลาสากลเชิงพิกัด ... )
เหมืองเน้นหนัก โซนเวลาตัวเองจะไม่ถูกเก็บไว้ มันเป็นตัวดัดแปลงอินพุตที่ใช้ในการคำนวณเวลา UTC ตามที่จัดเก็บ - หรือและตัวดัดแปลงเอาท์พุทที่ใช้ในการคำนวณเวลาท้องถิ่นที่จะแสดง - ด้วยออฟเซ็ตเขตเวลาต่อท้าย หากคุณไม่ผนวกออฟเซ็ตสำหรับtimestamptz
on อินพุตการตั้งค่าโซนเวลาปัจจุบันของเซสชันจะถือว่า การคำนวณทั้งหมดเสร็จสิ้นด้วยค่าเวลาประทับ UTC หากคุณมี (หรืออาจจะต้อง) timestamptz
การจัดการกับโซนเวลามากกว่าหนึ่งการใช้งาน
ไคลเอนต์เช่น psql หรือ pgAdmin หรือแอปพลิเคชันใด ๆ ที่สื่อสารผ่านlibpq (เช่น Ruby กับ pg gem) จะแสดงด้วยการประทับเวลาบวกกับออฟเซ็ตสำหรับเขตเวลาปัจจุบันหรือตามโซนเวลาที่ร้องขอ (ดูด้านล่าง) มันเป็นจุดเดิมเสมอเวลารูปแบบการแสดงแตกต่างกันไปเท่านั้น หรือตามที่คู่มือวางไว้ :
วันที่และเวลาที่ทราบเขตเวลาทั้งหมดจะถูกเก็บไว้ภายใน UTC พวกเขาจะถูกแปลงเป็นเวลาท้องถิ่นในโซนที่ระบุโดย
พารามิเตอร์การกำหนดค่าTimeZoneก่อนที่จะแสดงให้ลูกค้า
ลองพิจารณาตัวอย่างง่าย ๆ นี้ (ใน psql):
db = # SELECT timestamptz '2012-03-05 20:00 +03 ';
timestamptz
------------------------
2012-03-05 18:00:00 +01
เหมืองเน้นหนัก เกิดอะไรขึ้นที่นี่?
ฉันเลือกเขตเวลาโดยพลการ+3
สำหรับตัวอักษรอินพุต เพื่อ Postgres 2012-03-05 17:00:00
นี้เป็นเพียงหนึ่งในหลายวิธีที่จะป้อนข้อมูลการประทับเวลา ผลลัพธ์ของแบบสอบถามจะปรากฏขึ้นสำหรับการตั้งค่าโซนเวลาปัจจุบันเวียนนา / ออสเตรียในการทดสอบของฉันซึ่งมีการชดเชย+1
ในช่วงฤดูหนาวและ+2
ในช่วงฤดูร้อน: 2012-03-05 18:00:00+01
เพราะมันอยู่ในช่วงฤดูหนาว
Postgres ลืมวิธีการป้อนค่านี้ไปแล้ว ทั้งหมดที่จำได้คือค่าและชนิดข้อมูล เช่นเดียวกับตัวเลขทศนิยม numeric '003.4'
, numeric '3.40'
หรือnumeric '+3.4'
- ผลทั้งหมดในมูลค่าภายในเดียวกันแน่นอน
AT TIME ZONE
ทันทีที่คุณเข้าใจตรรกะนี้คุณสามารถทำอะไรก็ได้ที่คุณต้องการ สิ่งที่ขาดหายไปในตอนนี้เป็นเครื่องมือในการแปลหรือแสดงตัวอักษรเวลาประทับตามโซนเวลาที่ระบุ นั่นคือสิ่งที่AT TIME ZONE
โครงสร้างเข้ามามีสองกรณีใช้ที่แตกต่างกัน timestamptz
ถูกแปลงเป็นtimestamp
และในทางกลับกัน
ในการเข้าสู่ UTC timestamptz
2012-03-05 17:00:00+0
:
SELECT timestamp '2012-03-05 17:00:00' AT TIME ZONE 'UTC'
... ซึ่งเทียบเท่ากับ:
SELECT timestamptz '2012-03-05 17:00:00 UTC'
หากต้องการแสดงจุดในเวลาเดียวกันเป็น EST timestamp
(เวลามาตรฐานตะวันออก):
SELECT timestamp '2012-03-05 17:00:00' AT TIME ZONE 'UTC' AT TIME ZONE 'EST'
ที่เหมาะสมเป็นครั้งที่สองAT TIME ZONE 'UTC'
คนแรกที่ตีความtimestamp
คุ้มค่าเป็น (รับ) UTC timestamptz
ประทับเวลากลับชนิด อันที่สองแปลงtimestamptz
ไปเป็นtimestamp
ในเขตเวลาที่กำหนด 'EST' - นาฬิกาในเขตเวลา EST แสดงเวลาที่ไม่ซ้ำกันในเวลานี้
ตัวอย่าง
SELECT ts AT TIME ZONE 'UTC'
FROM (
VALUES
(1, timestamptz '2012-03-05 17:00:00+0')
, (2, timestamptz '2012-03-05 18:00:00+1')
, (3, timestamptz '2012-03-05 17:00:00 UTC')
, (4, timestamp '2012-03-05 11:00:00' AT TIME ZONE '+6')
, (5, timestamp '2012-03-05 17:00:00' AT TIME ZONE 'UTC')
, (6, timestamp '2012-03-05 07:00:00' AT TIME ZONE 'US/Hawaii') -- ①
, (7, timestamptz '2012-03-05 07:00:00 US/Hawaii') -- ①
, (8, timestamp '2012-03-05 07:00:00' AT TIME ZONE 'HST') -- ①
, (9, timestamp '2012-03-05 18:00:00+1') -- ② loaded footgun!
) t(id, ts);
ผลตอบแทนที่ 8 (หรือ 9) เหมือนแถวกับคอลัมน์ timestamptz 2012-03-05 17:00:00
ถือประทับเวลา แถวที่ 9 เกิดขึ้นเพื่อทำงานในเขตเวลาของฉัน แต่เป็นกับดักที่ชั่วร้าย ดูด้านล่าง
ows แถวที่ 6 - 8 ที่มีชื่อเขตเวลาและตัวย่อเขตเวลาสำหรับเวลาฮาวายนั้นขึ้นอยู่กับ DST (ปรับเวลาตามฤดูกาล) และอาจแตกต่างกันไป ชื่อเขตเวลาเช่น'US/Hawaii'
นั้นทราบถึงกฎ DST และการเปลี่ยนแปลงทางประวัติศาสตร์ทั้งหมดโดยอัตโนมัติในขณะที่ตัวย่อเช่นHST
นั้นเป็นเพียงรหัสใบ้สำหรับออฟเซ็ตคงที่ คุณอาจจำเป็นต้องใช้ตัวย่ออื่นสำหรับฤดูร้อน / เวลามาตรฐาน ชื่ออย่างถูกต้องตีความใด ๆประทับเวลาที่เขตเวลาที่กำหนด ย่อมีราคาถูก แต่จะต้องมีการหนึ่งที่เหมาะสมสำหรับการประทับเวลาที่กำหนด:
เวลาออมแสงไม่ได้เป็นความคิดที่เจิดจ้าที่สุดเท่าที่มนุษย์เคยมีมา
②แถว 9 ที่ทำเครื่องหมายว่าเป็นปืนพกเท้าโหลดนั้นเหมาะกับฉันแต่เป็นเรื่องบังเอิญเท่านั้น ถ้าคุณโยนอย่างชัดเจนตัวอักษรเพื่อtimestamp [without time zone]
, เขตเวลาใดก็ได้ชดเชยจะถูกละเว้น ! ใช้การประทับเวลาเปลือยเท่านั้น จากนั้นค่าจะถูกรวมเข้าtimestamptz
กับตัวอย่างเพื่อให้ตรงกับประเภทคอลัมน์ สำหรับขั้นตอนนี้การtimezone
ตั้งค่าของเซสชันปัจจุบันจะถือว่าเป็นเขตเวลาเดียวกัน+1
ในกรณีของฉัน (ยุโรป / เวียนนา) แต่อาจไม่ใช่ในกรณีของคุณ - ซึ่งจะส่งผลให้ค่าที่แตกต่าง กล่าวโดยย่อ: อย่าโยนtimestamptz
ตัวอักษรลงไปtimestamp
หรือคุณจะสูญเสียเขตเวลาชดเชย
คำถามของคุณ
ผู้ใช้เก็บเวลาหนึ่งพูด 17 มีนาคม 2012 เวลา 19.00 น. ฉันไม่ต้องการให้มีการแปลงเขตเวลาหรือเขตเวลาที่จะจัดเก็บ
เขตเวลาจะไม่ถูกจัดเก็บ ใช้วิธีใดวิธีหนึ่งข้างต้นเพื่อป้อนเวลาประทับ UTC
ฉันใช้เขตเวลาที่ผู้ใช้ระบุเพื่อรับบันทึก 'ก่อนหน้า' หรือ 'หลัง' เวลาปัจจุบันในเขตเวลาท้องถิ่นของผู้ใช้
คุณสามารถใช้หนึ่งแบบสอบถามสำหรับลูกค้าทั้งหมดในเขตเวลาที่แตกต่างกัน
สำหรับเวลาสากลทั้งหมด:
SELECT * FROM tbl WHERE time_col > (now() AT TIME ZONE 'UTC')::time
สำหรับเวลาตามเวลาท้องถิ่น:
SELECT * FROM tbl WHERE time_col > now()::time
ไม่เบื่อกับข้อมูลพื้นหลังใช่ไหม? มีมากในคู่มือ