DateTime เทียบกับ DateTimeOffset


742

ขณะนี้เรามีวิธีมาตรฐานในการจัดการกับ. NET DateTimeในวิธีการตระหนักถึงเขตเวลา: เมื่อใดก็ตามที่เราสร้าง a DateTimeเราจะทำใน UTC (เช่นใช้DateTime.UtcNow) และเมื่อใดก็ตามที่เราแสดงหนึ่งเราแปลงกลับจาก UTC เป็นเวลาท้องถิ่นของผู้ใช้ .

ใช้งานได้ดี แต่ฉันได้อ่านเกี่ยวกับDateTimeOffsetวิธีจับเวลาท้องถิ่นและเวลา UTC ในวัตถุเอง ดังนั้นคำถามคือสิ่งที่จะได้ประโยชน์จากการใช้DateTimeOffsetเมื่อเทียบกับสิ่งที่เราได้ทำไปแล้ว?


3
มีคำตอบที่ดีบางข้อด้านล่าง แต่ฉันยังคงสงสัยว่าถ้ามีอะไรจะทำให้คุณเริ่มใช้ DateTimeOffset
HappyNomad


เมื่อพูดถึงพื้นที่จัดเก็บstackoverflow.com/questions/4715620/…ก็น่าสนใจเช่นกัน
Dejan

คำตอบ:


1169

DateTimeOffsetเป็นตัวแทนของเวลาทันที (หรือเรียกอีกอย่างว่าเวลาสัมบูรณ์ ) โดยที่ฉันหมายถึงช่วงเวลาที่เป็นสากลสำหรับทุกคน (ไม่ใช่การบัญชีสำหรับวินาทีกระโดดหรือผลกระทบความสัมพันธ์ของการขยายเวลา ) วิธีที่จะเป็นตัวแทนของเวลาทันทีก็คือกับDateTimeที่เป็น.KindDateTimeKind.Utc

สิ่งนี้แตกต่างจากเวลาในปฏิทิน (หรือเรียกอีกอย่างว่าเวลาทางแพ่ง ) ซึ่งเป็นตำแหน่งในปฏิทินของใครบางคนและมีปฏิทินที่แตกต่างกันมากมายทั่วโลก เราขอเรียกร้องเหล่านี้ปฏิทินโซนเวลา ปฏิทินเวลาเป็นตัวแทนจากDateTimeที่.Kindเป็นหรือDateTimeKind.Unspecified DateTimeKind.Localและ.Localมีความหมายเฉพาะในสถานการณ์ที่คุณมีความเข้าใจโดยนัยเกี่ยวกับตำแหน่งของคอมพิวเตอร์ที่ใช้ผลลัพธ์ (ตัวอย่างเช่นเวิร์กสเตชันของผู้ใช้)

ดังนั้นแล้วทำไมDateTimeOffsetแทนที่จะ UTC เราจะต้องDateTime? มันเป็นเรื่องของมุมมอง ลองใช้การเปรียบเทียบเราจะแกล้งทำเป็นช่างภาพ

ลองนึกภาพคุณกำลังยืนอยู่บนไทม์ไลน์ของปฏิทินเล็งกล้องไปที่บุคคลบนไทม์ไลน์ที่วางด้านหน้าของคุณ คุณจัดเรียงกล้องของคุณตามกฎของเขตเวลาของคุณ - ซึ่งเปลี่ยนแปลงเป็นระยะเนื่องจากการปรับเวลาตามฤดูกาลหรือเนื่องจากการเปลี่ยนแปลงอื่น ๆ ตามคำนิยามทางกฎหมายของเขตเวลาของคุณ (คุณไม่มีมือที่มั่นคงกล้องจึงสั่นคลอน)

คนที่ยืนอยู่ในภาพถ่ายจะเห็นมุมที่กล้องของคุณมาจาก หากคนอื่นกำลังถ่ายรูปพวกเขาอาจมาจากมุมที่แตกต่างกัน นี่คือOffsetส่วนที่DateTimeOffsetแสดงถึง

ดังนั้นหากคุณติดป้ายกำกับกล้อง "เวลาตะวันออก" บางครั้งคุณก็ชี้จาก -5 และบางครั้งคุณก็ชี้จาก -4 มีกล้องอยู่ทั่วทุกมุมโลกสิ่งต่าง ๆ ที่มีป้ายกำกับและทั้งหมดชี้ไปที่ไทม์ไลน์ทันทีเดียวกันจากมุมที่แตกต่างกัน บางคนอยู่ติดกับ (หรือด้านบน) ดังนั้นเพียงแค่รู้ว่าออฟเซ็ตไม่เพียงพอที่จะกำหนดเขตเวลาที่เกี่ยวข้องกับเวลา

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

การแสดงภาพเวลาเทียบกับปฏิทินทันที

ดังนั้น - อุปมานี้บอกอะไรเรา มันมีแนวทางง่ายๆ

  • DateTimeหากคุณกำลังเป็นตัวแทนของเวลาเมื่อเทียบกับบางสถานที่โดยเฉพาะอย่างยิ่งเป็นตัวแทนในเวลาปฏิทินด้วย เพียงให้แน่ใจว่าคุณไม่ได้สับสนกับปฏิทินอื่น Unspecifiedควรเป็นข้อสมมุติของคุณ จะเป็นประโยชน์เฉพาะที่มาจากLocal DateTime.Nowตัวอย่างเช่นผมอาจได้รับDateTime.Nowและบันทึกไว้ในฐานข้อมูล - Unspecifiedแต่เมื่อฉันเอามันผมต้องคิดว่ามันเป็น ฉันไม่สามารถเชื่อถือได้ว่าปฏิทินในพื้นที่ของฉันเป็นปฏิทินเดียวกับที่เคยใช้มา

  • หากคุณต้องมั่นใจในช่วงเวลาหนึ่งเสมอตรวจสอบให้แน่ใจว่าคุณได้แสดงเวลาทันที ใช้DateTimeOffsetเพื่อบังคับใช้หรือใช้ UTC DateTimeตามแบบแผน

  • หากคุณต้องการติดตามช่วงเวลาทันที แต่คุณต้องการทราบว่า "ผู้ใช้คิดว่าเวลาใดในปฏิทินท้องถิ่นของพวกเขา" - แล้วคุณจะต้องDateTimeOffsetใช้ สิ่งนี้สำคัญมากสำหรับระบบบอกเวลา - ทั้งเรื่องของเทคนิคและข้อกฎหมาย

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

    มันควรที่จะชี้ให้เห็นว่าNoda TimeมีการเรียกZonedDateTimeสิ่งนี้ในขณะที่. Net base class library ไม่มีอะไรคล้ายกัน คุณจะต้องเก็บทั้งค่าDateTimeOffsetและTimeZoneInfo.Idค่า

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

ต่อไปนี้เป็นบิตเล็ก ๆ น้อย ๆ เกี่ยวกับการDateTimeOffsetสำรองข้อมูลการเปรียบเทียบนี้และเคล็ดลับในการทำให้มันตรง:

  • หากคุณเปรียบเทียบสองDateTimeOffsetค่าพวกเขาจะถูกทำให้เป็นมาตรฐานแรกเป็นออฟเซ็ตก่อนที่จะเปรียบเทียบ ในคำอื่น ๆ2012-01-01T00:00:00+00:00และ2012-01-01T02:00:00+02:00อ้างถึงช่วงเวลาทันทีเดียวกันและจึงเทียบเท่า

  • ถ้าคุณกำลังทำทดสอบหน่วยใดและจะต้องมีบางอย่างของการชดเชยการทดสอบทั้งDateTimeOffsetคุ้มค่าและ.Offsetสถานที่ให้บริการแยกต่างหาก

  • มีการแปลงโดยนัยทางเดียวที่สร้างไว้ภายใน. NET Framework ที่ให้คุณส่งผ่านDateTimeไปยังDateTimeOffsetพารามิเตอร์หรือตัวแปรใด ๆ เมื่อทำเช่นนั้นเรื่อง ถ้าคุณผ่านชนิด UTC ก็จะดำเนินการด้วยศูนย์ชดเชย แต่ถ้าคุณผ่านการอย่างใดอย่างหนึ่งหรือก็จะถือว่าเป็นท้องถิ่น โดยพื้นฐานแล้วกรอบบอกว่า "เอาล่ะคุณขอให้ฉันแปลงเวลาของปฏิทินเป็นเวลาทันที แต่ฉันก็ไม่รู้ว่ามันมาจากไหนดังนั้นฉันแค่จะใช้ปฏิทินท้องถิ่น" นี่เป็น gotcha ขนาดใหญ่ถ้าคุณโหลดไฟล์ที่ไม่ระบุในคอมพิวเตอร์ด้วยเขตเวลาอื่น (IMHO - นั่นควรจะเป็นข้อยกเว้น - แต่ไม่เป็นเช่นนั้น).Kind.Local.UnspecifiedDateTime

เสียบไร้ยางอาย:

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


4
@ZackJannsen หากคุณมี a DateTimeOffsetใน C # คุณควรจะยืนยันใน a DATETIMEOFFSETSQL Server DATETIME2หรือเพียงแค่DATETIME(ขึ้นอยู่กับช่วงที่ต้องการ) นั้นดีสำหรับDateTimeค่าปกติ ใช่ - คุณสามารถแก้ไขเวลาท้องถิ่นได้จากการจับคู่เขตเวลา + dto หรือ utc ความแตกต่างคือ - คุณต้องการคำนวณกฎด้วยการแก้ไขแต่ละครั้งหรือไม่หรือคุณต้องการคำนวณใหม่หรือไม่ ในหลายกรณี (บางครั้งสำหรับข้อกังวลทางกฎหมาย) DTO เป็นตัวเลือกที่ดีกว่า
Matt Johnson-Pint

3
@ZackJannsen สำหรับส่วนที่สองของคำถามของคุณฉันอยากจะแนะนำให้ทำฝั่งเซิร์ฟเวอร์ให้ได้มากที่สุด Javascript นั้นยอดเยี่ยมสำหรับการคำนวณเขตเวลา ถ้าคุณต้องทำมันใช้หนึ่งในห้องสมุดเหล่านี้ แต่ฝั่งเซิร์ฟเวอร์นั้นดีที่สุด หากคุณมีคำถามเพิ่มเติมอื่น ๆ โปรดเริ่มต้นคำถาม SO ใหม่สำหรับพวกเขาและฉันจะตอบถ้าฉันสามารถ ขอบคุณ
Matt Johnson-Pint

4
@ JoaoLeme - ขึ้นอยู่กับว่าคุณได้รับจากที่ไหน คุณถูกต้องว่าถ้าคุณพูดDateTimeOffset.Nowบนเซิร์ฟเวอร์คุณจะได้รับการชดเชยของเซิร์ฟเวอร์แน่นอน ประเด็นก็คือDateTimeOffsetประเภทสามารถรักษาออฟเซตนั้น คุณสามารถทำได้อย่างง่ายดายบนไคลเอนต์ส่งไปยังเซิร์ฟเวอร์แล้วเซิร์ฟเวอร์ของคุณจะรู้ว่าออฟเซ็ตของลูกค้า
Matt Johnson-Pint

8
รักการเปรียบเทียบกล้องจริงๆ
Sachin Kainth

2
ใช่ที่ถูกต้อง. ยกเว้นว่า DTO จะถูกเก็บไว้เป็นคู่ (เวลาท้องถิ่น, ออฟเซ็ต) ไม่ใช่คู่ (utc เวลา, ออฟเซ็ต) กล่าวอีกนัยหนึ่งการชดเชยจาก UTC จะปรากฏในเวลาท้องถิ่นแล้ว หากต้องการแปลงกลับเป็น utc ให้กลับเครื่องหมายของออฟเซ็ตแล้วปรับใช้กับเวลาท้องถิ่น
Matt Johnson-Pint

328

จาก Microsoft:

สิ่งเหล่านี้ใช้สำหรับค่า DateTimeOffset พบได้ทั่วไปมากกว่าค่าของ DateTime ดังนั้น DateTimeOffset จึงควรพิจารณาวันที่และเวลาเริ่มต้นสำหรับการพัฒนาแอปพลิเคชัน

แหล่งที่มา: "การเลือกระหว่าง DateTime, DateTimeOffset, TimeSpan และ TimeZoneInfo" , MSDN

เราใช้DateTimeOffsetเกือบทุกอย่างกับแอปพลิเคชันของเราที่มีจุดเฉพาะในเวลา (เช่นเมื่อมีการสร้าง / อัพเดทบันทึก) เราใช้DATETIMEOFFSETใน SQL Server 2008 ด้วยเช่นกัน

ฉันเห็นDateTimeว่ามีประโยชน์เมื่อคุณต้องการจัดการกับวันที่เท่านั้นเวลาเท่านั้นหรือจัดการกับทั้งในแง่สามัญ ตัวอย่างเช่นถ้าคุณมีการเตือนภัยที่คุณต้องการที่จะไปปิดทุกวันเวลา 07:00 คุณสามารถเก็บว่าในDateTimeการใช้DateTimeKindของUnspecifiedเพราะคุณต้องการที่จะไปปิดที่ 07:00 โดยไม่คำนึงถึงเวลา DateTimeOffsetแต่ถ้าคุณต้องการที่จะเป็นตัวแทนประวัติศาสตร์ของเหตุการณ์ปลุกคุณจะใช้

ใช้ความระมัดระวังเมื่อใช้การผสมผสานDateTimeOffsetและDateTimeโดยเฉพาะอย่างยิ่งเมื่อกำหนดและเปรียบเทียบระหว่างประเภท นอกจากนี้ให้เปรียบเทียบDateTimeอินสแตนซ์ที่เหมือนกันเท่านั้นDateTimeKindเพราะDateTimeละเว้นเขตเวลาชดเชยเมื่อเปรียบเทียบ


146
คำตอบที่ได้รับการยอมรับนั้นยาวเกินไปและมีการเปรียบเทียบอย่างตึงเครียดนี่เป็นคำตอบที่ดีและกระชับยิ่งขึ้น IMO
nexus บอกว่า

10
ฉันจะบอกว่าฉันชอบคำตอบนี้ด้วยและเพิ่มขึ้น แม้ว่าในส่วนสุดท้าย - แม้จะมั่นใจKindเหมือนกันการเปรียบเทียบอาจมีข้อผิดพลาด หากทั้งสองฝ่ายมีDateTimeKind.Unspecifiedคุณไม่ทราบว่าพวกเขามาจากเขตเวลาเดียวกัน หากทั้งสองฝ่ายDateTimeKind.Local, ส่วนใหญ่รถจะไปได้ดี แต่คุณอาจจะยังคงมีข้อผิดพลาดคือด้านหนึ่งเป็นที่คลุมเครือในเขตเวลาท้องถิ่น จริงๆDateTimeKind.Utcการเปรียบเทียบเท่านั้นจะเข้าใจผิดได้และใช่DateTimeOffsetเป็นที่ต้องการ (ไชโย!)
Matt Johnson-Pint

1
+1 ฉันจะเพิ่มสิ่งนี้: ประเภทข้อมูลที่คุณเลือกควรสะท้อนถึงเจตนาของคุณ อย่าใช้ DateTimeOffset ทุกที่เพียงทำให้เกิด หาก Offset สำคัญสำหรับการคำนวณและการอ่าน - จาก / Persisting-To DataBase ของคุณให้ใช้ DateTimeOffset หากไม่สำคัญให้ใช้ DateTime เพื่อให้คุณเข้าใจ (โดยดูที่ DataType) ว่า Offset ไม่ควรมีปัญหาและไทม์สควรยังคงสัมพันธ์กับ Locality ของเซิร์ฟเวอร์ / เครื่องของคุณ C # Code ของคุณทำงานอยู่
MikeTeeVee

"แต่ถ้าคุณต้องการแสดงประวัติของการเตือนภัยคุณจะใช้ DateTimeOffset" คุณสนใจที่จะอธิบายว่าทำไมคุณถึงคิดว่านี่คืออะไร? ฉันสามารถกรอกข้อมูลโดยการอ่านข้อมูลทั้งหมดในหน้านี้ แต่บางทีคุณอาจให้ข้อมูลดังกล่าวในลักษณะที่อ่านง่ายเช่นกัน นี่เป็นคำตอบที่อ่านง่ายมาก
Barrosy

77

DateTime สามารถจัดเก็บได้สองครั้งเท่านั้นเวลาท้องถิ่นและ UTC ชนิดคุณสมบัติบ่งชี้ว่า

DateTimeOffset ขยายตัวโดยการจัดเก็บเวลาท้องถิ่นจากที่ใดก็ได้ในโลก นอกจากนี้ยังเก็บออฟเซ็ตระหว่างเวลาท้องถิ่นกับ UTC โปรดทราบว่า DateTime ไม่สามารถทำสิ่งนี้ได้เว้นแต่คุณจะเพิ่มสมาชิกพิเศษให้กับชั้นเรียนของคุณเพื่อเก็บ UTC offset หรือเคยทำงานกับ UTC ซึ่งในตัวเองเป็นความคิดที่ดี btw


33

มีบางสถานที่ที่DateTimeOffsetเหมาะสม หนึ่งคือเมื่อคุณจัดการกับเหตุการณ์ที่เกิดขึ้นและประหยัดเวลากลางวัน สมมติว่าฉันต้องการตั้งเวลาปลุกที่ 9am ทุกวัน ถ้าผมใช้ "เก็บไว้เป็นเวลา UTC จอแสดงผลเป็นเวลาท้องถิ่น" กฎแล้วปลุกจะไปปิดที่แตกต่างกันเวลากลางวันเวลาออมทรัพย์มีผล

อาจมีคนอื่น ๆ แต่ตัวอย่างข้างต้นเป็นจริงอย่างหนึ่งที่ฉันเคยพบในอดีต (นี่คือก่อนที่จะเพิ่มDateTimeOffsetBCL - โซลูชั่นของฉันในเวลานั้นคือการเก็บเวลาในเขตเวลาท้องถิ่นอย่างชัดเจนและบันทึก ข้อมูลเขตเวลาอยู่เคียงข้าง: โดยพื้นฐานแล้วอะไรDateTimeOffsetจะเกิดขึ้นภายใน)


12
DateTimeOffset ไม่ได้แก้ไขปัญหา DST
JarrettV

2
การใช้คลาส TimeZoneInfo มีกฎสำหรับ DST หากคุณอยู่ใน. net 3.5 ขึ้นไปให้ใช้คลาส TimeZone หรือ TimeZoneInfo เพื่อจัดการกับวันที่ที่ต้องจัดการกับ Daylight Saving Time ในรูปแบบ conjunciton พร้อมกับเขตเวลาชดเชย
Zack Jannsen

1
ใช่ตัวอย่างที่ดีของข้อยกเว้น (แอพเตือน) แต่เมื่อเวลามีความสำคัญมากกว่าวันที่คุณควรจัดเก็บแยกไว้ในโครงสร้างข้อมูลกำหนดการของคุณสำหรับแอปพลิเคชันเช่นประเภทที่เกิดขึ้น = รายวันและเวลา = 09:00 จุดที่นี่คือนักพัฒนาจะต้องตระหนักถึงชนิดของวันที่พวกเขากำลังบันทึกการคำนวณหรือนำเสนอให้กับผู้ใช้ โดยเฉพาะอย่างยิ่งแอพมีแนวโน้มที่จะเป็นที่นิยมมากขึ้นทั่วโลกในขณะนี้เรามีอินเทอร์เน็ตในฐานะที่เป็นมาตรฐานและแอพสโตร์ขนาดใหญ่สำหรับเขียนซอฟต์แวร์ ในฐานะที่เป็นโหนดด้านข้างฉันต้องการเห็น Microsoft เพิ่มโครงสร้าง Date and Time แยกจากกัน
Tony Wall

3
สรุปความคิดเห็นของ Jarrett และ Zack: ดูเหมือนว่า DateTimeOffset เพียงอย่างเดียวจะไม่จัดการกับปัญหา DST แต่การใช้ DateTimeOffset ร่วมกับ TimeZoneInfo จะจัดการกับมัน นี่ไม่แตกต่างจาก DateTime โดยที่ชนิดเป็น Utc ในทั้งสองกรณีฉันต้องรู้เขตเวลา (ไม่ใช่แค่ออฟเซ็ต) ของปฏิทินที่ฉันคาดการณ์ไว้ (ฉันอาจเก็บข้อมูลนั้นไว้ในโปรไฟล์ของผู้ใช้หรือรับจากไคลเอนต์ (เช่น Windows) ถ้าเป็นไปได้) ใช่มั้ย
Jeremy Cook

"มีสถานที่ไม่กี่แห่งที่ DateTimeOffset เหมาะสม" --- เนื้อหามันมักจะทำให้รู้สึกมากกว่าไม่
Ronnie Overby

23

ความแตกต่างที่สำคัญที่สุดคือ DateTime ไม่เก็บข้อมูลเขตเวลาในขณะที่ DateTimeOffset ทำ

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

ตัวอย่างเช่นถ้าคุณเป็นอันดับค่า DateTime กับชนิด = ท้องถิ่นโดยใช้ Json.Net และรูปแบบวันที่ ISO, 2015-08-05T07:00:00-04คุณจะได้รับสตริงเหมือน ขอให้สังเกตว่าส่วนสุดท้าย (-04) ไม่มีส่วนเกี่ยวข้องกับ DateTime ของคุณหรือออฟเซ็ตใด ๆ ที่คุณใช้ในการคำนวณ ... มันเป็นเพียงการชดเชยโซนเวลาของเซิร์ฟเวอร์เท่านั้น

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


14
ด้วยคำตอบทั้งหมดข้างต้นฉันสงสัยว่าทำไมไม่มีใครใส่ใจที่จะเขียนประโยคเดียวของคุณที่รวมมันทั้งหมดThe most important distinction is that DateTime does not store time zone information, while DateTimeOffset does.
Korayem

9
DateTimeOffset ไม่เก็บข้อมูลเขตเวลา MS doc หัวข้อ "การเลือกระหว่าง DateTime, DateTimeOffset, TimeSpan และ TimeZoneInfo" ระบุถึงการระบุนี้: "ค่า DateTimeOffset ไม่ได้เชื่อมโยงกับเขตเวลาใดเขตหนึ่ง แต่สามารถกำเนิดจากเขตเวลาที่หลากหลาย" ที่กล่าวว่า DateTimeOffset IS เขตเวลา AWARE มีการชดเชยจาก UTC ซึ่งสร้างความแตกต่างทั้งหมดและเป็นสาเหตุที่ MS แนะนำคลาสเริ่มต้นเมื่อจัดการกับการพัฒนาแอพที่เกี่ยวข้องกับข้อมูลวันที่ หากคุณสนใจว่าเขตเวลาที่เฉพาะเจาะจงข้อมูลมาจากไหนคุณต้องเก็บรักษาไว้แยกต่างหาก
stonedauwg

1
ใช่ แต่อย่างที่ปรากฏในหลาย ๆ สถานที่ + หรือ - ชั่วโมงไม่ได้พูดถึงว่าคุณอยู่ในเขตเวลาใดและในที่สุดก็ไร้ประโยชน์ ขึ้นอยู่กับสิ่งที่คุณต้องทำคุณสามารถเก็บวันที่และเวลาเป็นชนิดไม่ระบุและเก็บรหัสของเขตเวลาและฉันคิดว่าคุณดีกว่าจริง ๆ
Arwin

13

รหัสชิ้นนี้จากMicrosoftอธิบายทุกอย่าง:

// Find difference between Date.Now and Date.UtcNow
  date1 = DateTime.Now;
  date2 = DateTime.UtcNow;
  difference = date1 - date2;
  Console.WriteLine("{0} - {1} = {2}", date1, date2, difference);

  // Find difference between Now and UtcNow using DateTimeOffset
  dateOffset1 = DateTimeOffset.Now;
  dateOffset2 = DateTimeOffset.UtcNow;
  difference = dateOffset1 - dateOffset2;
  Console.WriteLine("{0} - {1} = {2}", 
                    dateOffset1, dateOffset2, difference);
  // If run in the Pacific Standard time zone on 4/2/2007, the example
  // displays the following output to the console:
  //    4/2/2007 7:23:57 PM - 4/3/2007 2:23:57 AM = -07:00:00
  //    4/2/2007 7:23:57 PM -07:00 - 4/3/2007 2:23:57 AM +00:00 = 00:00:00

9

คำตอบส่วนใหญ่ดี แต่ฉันคิดว่าจะเพิ่มลิงก์เพิ่มเติมของ MSDN สำหรับข้อมูลเพิ่มเติม



7

ความแตกต่างที่สำคัญคือDateTimeOffsetสามารถใช้ร่วมกับTimeZoneInfoการแปลงเป็นเวลาท้องถิ่นในเขตเวลาอื่นนอกเหนือจากเวลาปัจจุบัน

สิ่งนี้มีประโยชน์ในแอปพลิเคชันเซิร์ฟเวอร์ (เช่น ASP.NET) ที่ผู้ใช้เข้าถึงได้ในเขตเวลาที่แตกต่างกัน


3
@Bugeo Bugeo เป็นจริง แต่มีความเสี่ยง คุณสามารถเปรียบเทียบ DateTimes สองรายการโดยเรียก "ToUniversalTime" ครั้งแรกในแต่ละรายการ หากคุณมีค่าเดียวในการเปรียบเทียบที่เป็น DateTimeKind = ไม่ได้ระบุกลยุทธ์ของคุณจะล้มเหลว โอกาสในการเกิดความล้มเหลวนี้เป็นเหตุผลในการพิจารณา DateTimeOffset ผ่าน DateTime เมื่อต้องการแปลงเป็นเวลาท้องถิ่น
Zack Jannsen

ดังที่ได้กล่าวมาแล้วฉันคิดว่าในสถานการณ์นี้คุณดีกว่าในการเก็บ TimeZoneId มากกว่าการใช้ DateTimeOffset ซึ่งท้ายที่สุดแล้วไม่มีความหมายอะไรเลย
Arwin

2

ด้านลบอย่างเดียวของ DateTimeOffset ที่ฉันเห็นคือ Microsoft "ลืม" (ตามการออกแบบ) เพื่อสนับสนุนในระดับ XmlSerializer แต่มันถูกเพิ่มเข้าไปในคลาสยูทิลิตี้ XmlConvert

XmlConvert.ToDateTimeOffset

XmlConvert.ToString

ฉันพูดไปข้างหน้าและใช้ DateTimeOffset และ TimeZoneInfo เพราะผลประโยชน์ทั้งหมดเพียงแค่ระวังเมื่อสร้างเอนทิตีที่จะหรืออาจจะต่อเนื่องกันไปหรือจาก XML (วัตถุธุรกิจทั้งหมดแล้ว)

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