การจัดเก็บ DateTime (UTC) เทียบกับการจัดเก็บ DateTimeOffset


97

ฉันมักจะมี "ตัวสกัดกั้น" ที่อยู่ก่อนที่จะอ่าน / เขียนจาก / ไปยังฐานข้อมูลทำการแปลง DateTime (จากเวลา UTC เป็นเวลาท้องถิ่นและจากเวลาท้องถิ่นเป็น UTC) ดังนั้นฉันจึงสามารถใช้DateTime.Now(อนุพันธ์และการเปรียบเทียบ) ได้ทั่วทั้งระบบโดยไม่ต้องกังวล เกี่ยวกับเขตเวลา

เกี่ยวกับการทำให้เป็นอนุกรมและการย้ายข้อมูลระหว่างคอมพิวเตอร์ไม่จำเป็นต้องกังวลเนื่องจากวันที่และเวลาเป็น UTC เสมอ

ฉันควรจัดเก็บวันที่ของฉันต่อไป (SQL 2008 - วันที่และเวลา) ในรูปแบบ UTC หรือควรเก็บไว้โดยใช้DateTimeOffset(SQL 2008 - datetimeoffset)

วันที่ UTC ในฐานข้อมูล (ประเภทวันที่และเวลา) ใช้งานได้และเป็นที่รู้จักมานานแล้วทำไมต้องเปลี่ยน ข้อดีคืออะไร?

ฉันได้ดูบทความเช่นนี้แล้ว แต่ฉันไม่มั่นใจ 100% ความคิดใด ๆ ?


คำถามที่เกี่ยวข้อง: stackoverflow.com/questions/2532729/…
Oded

1
ดูเพิ่มเติม: DateTime vs DateTimeOffset - เขียนสำหรับ. Net แต่ใช้แนวคิดกับ SQL ด้วย
Matt Johnson-Pint

คำตอบ:


131

มีความแตกต่างอย่างมากอย่างหนึ่งที่คุณไม่สามารถใช้ UTC เพียงอย่างเดียวได้

  • หากคุณมีสถานการณ์เช่นนี้

    • เซิร์ฟเวอร์หนึ่งเครื่องและไคลเอนต์หลายตัว (ตามพื้นที่ทางภูมิศาสตร์ในเขตเวลาที่ต่างกัน )
    • ไคลเอนต์สร้างข้อมูลบางส่วนด้วยข้อมูลวันที่และเวลา
    • ลูกค้าจัดเก็บข้อมูลทั้งหมดไว้บนเซิร์ฟเวอร์ส่วนกลาง
  • จากนั้น:

    • datetimeoffset เก็บเวลาท้องถิ่นของไคลเอ็นต์และยังชดเชยเวลา UTC
    • ลูกค้าทุกคนทราบเวลา UTC ของข้อมูลทั้งหมดและยังเป็นเวลาท้องถิ่นในสถานที่ที่ข้อมูลนั้นเกิดขึ้น
  • แต่:

    • วันที่และเวลา UTC เก็บเฉพาะวันที่และเวลา UTCดังนั้นคุณจึงไม่มีข้อมูลเกี่ยวกับเวลาท้องถิ่นในตำแหน่งไคลเอ็นต์ที่ข้อมูลเกิดขึ้น
    • ไคลเอนต์อื่นไม่ทราบเวลาท้องถิ่นของสถานที่ที่ข้อมูลวันที่และเวลามาจาก
    • ไคลเอนต์รายอื่นสามารถคำนวณเวลาท้องถิ่นของตนจากฐานข้อมูลเท่านั้น (โดยใช้เวลา UTC) ไม่ใช่เวลาท้องถิ่นของไคลเอ็นต์ที่ข้อมูลเกิดขึ้น

ตัวอย่างง่ายๆคือระบบจองตั๋วเครื่องบิน ... ตั๋วเครื่องบินควรมี 2 ครั้ง: - เวลา "ขึ้นเครื่อง" (ในเขตเวลา "จาก" เมือง) - เวลา "ลงจอด" (ในเขตเวลาของเมือง "ปลายทาง")


2
นี่เป็นคำอธิบายที่ดีที่สุดที่ฉันได้อ่านเกี่ยวกับเวลาที่เหมาะสมและฉันได้อ่านมากสำหรับเราจากสิ่งนี้ดูเหมือนจะไม่เป็นเช่นนั้น เราได้รับเวลาใน UTC สำหรับข้อมูลภายนอกของเราและเราทราบตำแหน่งจากแหล่งอื่นหากจำเป็น (และไม่เคยมีมาก่อน) ขอบคุณที่ทำให้มันดูชัดเจน
Andrew Backer

20
คุณบอกว่า "datetimeoffset เก็บเวลา UTC และยังหักล้างกับเวลาท้องถิ่นของไคลเอ็นต์" แต่ datetimeoffset เก็บเวลา LOCAL + Offset หรือเวลา UTC + ออฟเซ็ตเท่ากับ +0
Serhii Kyslyi

แม้ว่าคุณจะสามารถส่ง DTO เป็น DT ได้เนื่องจากฐาน DT เป็น UTC (แม้ว่านี่จะเป็นขั้นตอนพิเศษสำหรับทุกคนที่ใช้ฐานข้อมูลและไม่มีเนื้อหาที่ง่ายไปกว่าการใช้เวลา UTC เพียงอย่างเดียว)
iliketocode

2
ดูเหมือนร้าน DateTmeOffset "เวลาท้องถิ่นและ UTC Offset" มากกว่าไม่ใช่ "เวลา UTC และเวลา UTC Offset" หากคุณแคสต์เป็นวันที่และเวลาหรือใช้ฟังก์ชันส่วนวันที่ใด ๆ คุณจะได้รับส่วนประกอบวันที่และเวลาภายใน
Triynko

" ลูกค้าทุกคนรู้เวลา UTC ของข้อมูลทั้งหมดและเวลาท้องถิ่นในสถานที่ที่ข้อมูลเกิด"แม้ว่าการจัดเก็บเป็นส่วนหนึ่งของฟิลด์วันที่จะรู้สึกผิดปกติในกรณีนั้น กรณีการใช้งานคืออะไร - นั่นคือทำไมคุณไม่ใช้ UTC และดึงออฟเซ็ตไปที่InputLocationId(หรือเอนทิตีปกติที่คล้ายกัน) จะมีการคำนวณที่เกี่ยวข้อง (สวัสดีข้อยกเว้น ... โดยเฉพาะคุณอินเดียนา ) แต่ก็ยังคงเป็นกระบวนการกำหนด - จากนั้นความสมดุลของตรรกะวันที่และเวลาของแอปนั้นตรงไปตรงมา
ruffin

23

คุณมีความถูกต้องอย่างยิ่งที่จะใช้ UTC สำหรับเวลาในอดีตทั้งหมด (เช่นมีการบันทึกเหตุการณ์ที่เกิดขึ้น) เป็นไปได้เสมอที่จะเปลี่ยนจาก UTC ไปเป็นเวลาท้องถิ่น แต่ไม่ใช่วิธีอื่นเสมอไป

ใช้เวลาท้องถิ่นเมื่อใด ตอบคำถามนี้:

หากรัฐบาลตัดสินใจเปลี่ยนการออมแสงโดยกะทันหันคุณต้องการเปลี่ยนแปลงข้อมูลนี้หรือไม่

เก็บเฉพาะเวลาท้องถิ่นหากคำตอบคือ "ใช่" เห็นได้ชัดว่าจะมีไว้สำหรับเดทในอนาคตเท่านั้นและโดยปกติจะเป็นเฉพาะวันที่ส่งผลกระทบต่อผู้คนไม่ทางใดก็ทางหนึ่ง

ทำไมต้องเก็บเขตเวลา / ออฟเซ็ต?

ประการแรกหากคุณต้องการบันทึกว่าค่าชดเชยสำหรับผู้ใช้ที่ทำการดำเนินการนั้นเป็นอย่างไรคุณน่าจะทำได้ดีที่สุดนั่นคือเมื่อเข้าสู่ระบบบันทึกตำแหน่งและเขตเวลาสำหรับผู้ใช้รายนั้น

ประการที่สองหากคุณต้องการแปลงสำหรับการแสดงผลคุณต้องมีตารางการเปลี่ยนค่าออฟเซ็ตเวลาท้องถิ่นทั้งหมดสำหรับเขตเวลานั้นเพียงแค่รู้ว่าค่าชดเชยปัจจุบันไม่เพียงพอเพราะหากคุณกำลังแสดงวันที่ / เวลาจากหกเดือนที่แล้วค่าชดเชยจะ จงแตกต่าง.


4
การแปลง UTC ของ Windows เป็นเวลาท้องถิ่นจะพิจารณาเมื่อเวลาออมแสงเปลี่ยนไปสำหรับวันที่ในอดีต ฉันไม่เห็นเหตุผลที่คุณต้องการจัดเก็บเวลาท้องถิ่นในกรณีนั้น
jamiegs

1
@ Jamiegs Windows ในอดีตเท่านั้นที่รู้ "ข้อมูลประวัติล่าสุด" (ตามที่มีคำใบ้ / ระบุไว้ในเอกสาร. NET DateTime) มันไม่ครอบคลุม

2
แน่นอนว่าคุณต้องจัดเก็บสถานที่จัดงานด้วยมิเช่นนั้นคุณจะไม่สามารถบอกได้ว่าเหตุการณ์นั้นเกิดขึ้นใน "เวลาท้องถิ่น"
keuleJ

20

DATETIMEOFFSET ช่วยให้คุณสามารถจัดเก็บเวลาท้องถิ่นและเวลา UTC ในฟิลด์เดียว

ช่วยให้สามารถรายงานได้ง่ายและมีประสิทธิภาพในเวลาท้องถิ่นหรือ UTC โดยไม่จำเป็นต้องประมวลผลข้อมูลเพื่อแสดงผล แต่อย่างใด

ข้อกำหนดที่พบบ่อยที่สุด 2 ข้อ ได้แก่ เวลาท้องถิ่นสำหรับรายงานท้องถิ่นและเวลา UTC สำหรับรายงานกลุ่ม

เวลาท้องถิ่นจะถูกเก็บไว้ในส่วน DATETIME ของ DATETIMEOFFSET และ OFFSET จาก UTC จะถูกเก็บไว้ในส่วน OFFSET ดังนั้นการแปลงจึงทำได้ง่ายและเนื่องจากไม่จำเป็นต้องมีความรู้เกี่ยวกับเขตเวลาที่ข้อมูลมาจึงสามารถทำได้ทั้งหมดที่ระดับฐานข้อมูล .

หากคุณไม่ต้องการให้เวลาลดลงเหลือเพียงมิลลิวินาทีเช่นเป็นนาทีหรือวินาทีคุณสามารถใช้ DATETIMEOFFSET (0) ได้ จากนั้นช่อง DATETIMEOFFSET จะต้องใช้พื้นที่เก็บข้อมูลเพียง 8 ไบต์เช่นเดียวกับ DATETIME

การใช้ DATETIMEOFFSET แทนที่จะเป็น UTC DATETIME จึงให้ความยืดหยุ่นประสิทธิภาพและความเรียบง่ายในการรายงานมากกว่า


กรอบงานเอนทิตีที่แย่เกินไปไม่มีวิธีใดในการเข้าถึงวันที่และเวลาท้องถิ่นของฟิลด์ datetimeoffset ทำให้ไม่สามารถสอบถามวันที่ในเครื่องได้
Triynko

@Triynko คุณสามารถอธิบายสิ่งที่คุณหมายถึง? ตัวอย่าง?
reidLinden
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.