แนวทางปฏิบัติที่ดีที่สุดสำหรับการปรับเวลาตามฤดูกาลและโซนเวลา [ปิด]


2046

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

หากคุณมีอะไรที่จะเพิ่มโปรดทำ

ระบบจำนวนมากขึ้นอยู่กับการรักษาเวลาที่ถูกต้องปัญหาคือการเปลี่ยนแปลงเวลาเนื่องจากการประหยัดเวลากลางวัน - เลื่อนนาฬิกาไปข้างหน้าหรือข้างหลัง

ตัวอย่างเช่นมีกฎเกณฑ์ทางธุรกิจในระบบการสั่งซื้อที่ขึ้นอยู่กับเวลาของการสั่งซื้อ - หากนาฬิกามีการเปลี่ยนแปลงกฎอาจไม่ชัดเจน เวลาของการสั่งซื้อควรจะคงอยู่อย่างไร? แน่นอนว่ามีหลายสถานการณ์ - อันนี้เป็นเพียงตัวอย่างหนึ่ง

  • คุณจัดการกับปัญหาการประหยัดเวลากลางวันอย่างไร
  • สมมติฐานอะไรบ้างที่เป็นส่วนหนึ่งของโซลูชันของคุณ (มองหาบริบทที่นี่)

ที่สำคัญถ้าไม่มากกว่านั้น:

  • คุณลองทำอะไรที่ไม่ได้ผล?
  • ทำไมมันไม่ทำงาน

ฉันสนใจที่จะเขียนโปรแกรม OS การคงอยู่ของข้อมูลและประเด็นอื่น ๆ ที่เกี่ยวข้องของปัญหา

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


2
@abatishchev - ด้วยวิธีนี้GETDATE()บน SQL จะเป็น UTC ( ตามใจชอบDateTime.Now) และเซิร์ฟเวอร์จะไม่ได้รับผลกระทบจากการเปลี่ยนแปลง DST อัตโนมัติใด ๆ
Oded

4
@Oded: ฉันสามารถยอมรับได้ว่าจะเพิ่ม "บนเซิร์ฟเวอร์" หรือไม่ แต่ก็ยังสามารถส่งผลกระทบต่อการใช้งานอื่นที่ต้องการเวลาท้องถิ่น ด้วยเหตุผลนี้และเหตุผลอื่น ๆ ฉันคิดว่าเป็นการดีกว่าที่จะขอเวลา Utc อย่างชัดเจน
abatishchev

7
UTC เป็นที่ต้องการของ GMT ทั้งคู่เพราะมันถูกกำหนดไว้อย่างแม่นยำมากขึ้นและเนื่องจากข้อกำหนดของ GMT ถูกทำให้สับสนในระบบปฏิบัติการ เป็นเรื่องปกติที่ผู้คนจะปฏิบัติต่อคำว่า "GMT" และ "UTC" แทนกัน แต่ไม่ได้ทั้งหมด สำหรับวัตถุประสงค์ของซอฟต์แวร์ / ระบบเกือบทั้งหมดให้ใช้ UTC ดูstackoverflow.com/questions/2292334/…
Chris Johnson

7
@JoshStodola - จอนสกีตของ ' คำตอบ '
Kenny Evitt

1
@ เกินคุณไม่สามารถคาดเดาได้ว่าเซิร์ฟเวอร์จะอยู่ใน UTC ฉันได้เห็นเซิร์ฟเวอร์ที่ใช้งานจริงซึ่งเขตเวลาเป็น "UTC" แต่มีการใช้ DST ดังนั้นจริง ๆ แล้วก็คือ UTC + 1 มานานกว่าครึ่งปี เห็นด้วยกับ @abatishchev ให้ชัดเจนและใช้งานDateTime.UtcNowและGETUTCDATE()มันยังแสดง devs อื่น ๆ ที่คุณคิดเกี่ยวกับมัน
ono2012

คำตอบ:


940

สรุปคำตอบและข้อมูลอื่น ๆ : (โปรดเพิ่มของคุณ)

ทำ:

  • เมื่อใดก็ตามที่คุณอ้างถึงช่วงเวลาที่แน่นอนให้คงเวลาไว้ตามมาตรฐานแบบรวมศูนย์ที่ไม่ได้รับผลกระทบจากการประหยัดเวลากลางวัน (GMT และ UTC เทียบเท่ากับเรื่องนี้ แต่เป็นที่ต้องการใช้คำว่า UTC โปรดสังเกตว่า UTC รู้จักกันในชื่อZuluหรือZ time)
  • หากคุณเลือกที่จะคงเวลาไว้โดยใช้ค่าเวลาท้องถิ่นให้รวมการชดเชยเวลาท้องถิ่นสำหรับเวลาเฉพาะจาก UTC (การชดเชยนี้อาจเปลี่ยนแปลงได้ตลอดทั้งปี) ดังนั้นการตีความเวลาสามารถตีความได้อย่างชัดเจนในภายหลัง
  • ในบางกรณีคุณอาจต้องเก็บทั้งเวลา UTC และเวลาท้องถิ่นที่เทียบเท่า บ่อยครั้งสิ่งนี้ทำกับสองฟิลด์ที่แยกจากกัน แต่บางแพลตฟอร์มรองรับdatetimeoffsetประเภทที่สามารถเก็บทั้งสองในฟิลด์เดียว
  • เมื่อเก็บเวลาประทับเป็นค่าตัวเลขให้ใช้เวลา Unix - ซึ่งเป็นจำนวนวินาทีทั้งหมดตั้งแต่1970-01-01T00:00:00Z(ไม่รวมวินาทีกระโดด) หากคุณต้องการความแม่นยำสูงกว่าให้ใช้มิลลิวินาทีแทน ค่านี้ควรยึดตาม UTC โดยไม่มีการปรับโซนเวลาใด ๆ
  • หากคุณอาจจำเป็นต้องแก้ไขการประทับเวลาในภายหลังให้ใส่รหัสเขตเวลาดั้งเดิมเพื่อให้คุณสามารถกำหนดได้ว่าการชดเชยอาจเปลี่ยนแปลงจากค่าเดิมที่บันทึกไว้หรือไม่
  • เมื่อกำหนดเวลาเหตุการณ์ในอนาคตมักจะต้องการเวลาท้องถิ่นแทน UTC เนื่องจากเป็นเรื่องปกติที่การชดเชยจะเปลี่ยน ดูคำตอบและโพสต์บล็อก
  • เมื่อจัดเก็บทั้งวันเช่นวันเกิดและวันครบรอบอย่าแปลงเป็น UTC หรือเขตเวลาอื่น
    • เมื่อเป็นไปได้ให้จัดเก็บในประเภทข้อมูลเฉพาะวันที่ซึ่งไม่รวมเวลาของวัน
    • หากประเภทดังกล่าวไม่สามารถใช้งานได้โปรดอย่าลืมช่วงเวลาของวันเมื่อตีความค่า หากคุณไม่สามารถมั่นใจได้ว่าเวลาจะถูกละเว้นให้เลือกเวลา 12.00 น. แทนที่จะเป็น 00:00 น. เที่ยงคืนเพื่อเป็นตัวแทนเวลาที่ปลอดภัยมากขึ้นในวันนั้น
  • โปรดจำไว้ว่าการออฟเซ็ตเขตเวลานั้นไม่ใช่จำนวนเต็มตลอดเวลา (ตัวอย่างเช่นเวลามาตรฐานของอินเดียคือ UTC + 05: 30 และเนปาลใช้ UTC + 05: 45)
  • หากใช้ Java ให้ใช้java.timeสำหรับ Java 8 และใหม่กว่า
    • มากของที่java.timeการทำงานจะกลับรังเพลิง Java 6 และ 7 ในThreeTen-ย้ายกลับห้องสมุด
    • ดัดแปลงเพิ่มเติมสำหรับ Android ต้น (<26) ในไลบรารีThreeTenABP
    • โครงการเหล่านี้อย่างเป็นทางการแทนที่เคารพJoda เวลาขณะนี้อยู่ในการบำรุงรักษาโหมด Joda-Time, ThreeTen-ย้ายกลับ, ThreeTen-Extra , java.timeเรียนและJSR 310นำโดยคนคนเดียวกัน, สตีเฟ่น Colebourne
  • ถ้าใช้.NETพิจารณาใช้Noda เวลา
  • ถ้าใช้ .NET โดยไม่ต้อง Noda เวลาพิจารณาว่ามักจะเป็นทางเลือกที่ดีกว่าDateTimeOffsetDateTime
  • ถ้าใช้ Perl ใช้DateTime
  • ถ้าใช้งูหลามใช้pytzหรือdateutil
  • หากใช้ JavaScript ให้ใช้moment.jsพร้อมกับส่วนขยายช่วงเวลา
  • หากใช้ PHP> 5.2 ให้ใช้การแปลงโซนเวลาแบบเนทีฟที่จัดทำโดยDateTimeและDateTimeZoneคลาส โปรดใช้ความระมัดระวังเมื่อใช้DateTimeZone::listAbbreviations()- ดูคำตอบ เพื่อให้ PHP มีข้อมูล Olson ที่ทันสมัยให้ติดตั้งแพคเกจtimezonedb PECL เป็นระยะ ดูคำตอบ
  • ถ้าใช้ C ++ ให้แน่ใจว่าการใช้ห้องสมุดที่ใช้อย่างถูกต้องดำเนินการฐานข้อมูลเขตเวลา IANA เหล่านี้รวมถึงcctz , ห้องไอซียูและโฮเวิร์ด Hinnant ของ "TZ" ห้องสมุด
    • อย่าใช้Boostสำหรับการแปลงเขตเวลา ในขณะที่APIอ้างว่าให้การสนับสนุนตัวระบุ IANA มาตรฐาน (aka "zoneinfo") แต่จะแมปข้อมูลเหล่านี้กับข้อมูลสไตล์ POSIX โดยไม่คำนึงถึงประวัติอันยาวนานของการเปลี่ยนแปลงแต่ละโซนอาจมี (นอกจากนี้ไฟล์ยังขาดการบำรุงรักษา)
  • ถ้าใช้สนิมใช้Chrono
  • กฎทางธุรกิจส่วนใหญ่ใช้เวลาแบบพลเรือนไม่ใช่ UTC หรือ GMT ดังนั้นวางแผนที่จะแปลงเวลาประทับ UTC เป็นเขตเวลาท้องถิ่นก่อนที่จะใช้ตรรกะแอปพลิเคชัน
  • โปรดจำไว้ว่าเขตเวลาและการออฟเซ็ตจะไม่คงที่และอาจเปลี่ยนแปลงได้ ตัวอย่างเช่นในอดีตสหรัฐอเมริกาและสหราชอาณาจักรใช้วันที่เดียวกันกับ 'spring forward' และ 'ถอยกลับ' อย่างไรก็ตามในปี 2007 สหรัฐอเมริกาได้เปลี่ยนวันที่ที่นาฬิกามีการเปลี่ยนแปลง ตอนนี้หมายความว่าเป็นเวลา 48 สัปดาห์ของปีความแตกต่างระหว่างเวลาลอนดอนและเวลานิวยอร์กคือ 5 ชั่วโมงและ 4 สัปดาห์ (3 ในฤดูใบไม้ผลิ 1 ในฤดูใบไม้ร่วง) เป็น 4 ชั่วโมง ระวังรายการเช่นนี้ในการคำนวณใด ๆ ที่เกี่ยวข้องกับหลายโซน
  • พิจารณาประเภทของเวลา (เวลาเหตุการณ์จริง, เวลาออกอากาศ, เวลาที่สัมพันธ์กัน, เวลาในอดีต, เวลาที่เกิดซ้ำ) องค์ประกอบใดบ้าง (การประทับเวลา, การชดเชยโซนเวลาและชื่อโซนเวลา) ที่คุณต้องจัดเก็บเพื่อการดึงที่ถูกต้อง - ดู "ประเภทเวลา" คำตอบนี้
  • รักษา OS, ฐานข้อมูลและไฟล์ tzdata ของแอปพลิเคชันให้ตรงกันระหว่างตัวเองกับส่วนที่เหลือของโลก
  • บนเซิร์ฟเวอร์ตั้งนาฬิกาฮาร์ดแวร์และนาฬิกา OS เป็น UTC แทนที่จะเป็นเขตเวลาท้องถิ่น
  • โดยไม่คำนึงถึงสัญลักษณ์แสดงหัวข้อก่อนหน้ารหัสฝั่งเซิร์ฟเวอร์รวมถึงเว็บไซต์ไม่ควรคาดหวังว่าโซนเวลาท้องถิ่นของเซิร์ฟเวอร์จะเป็นสิ่งใดโดยเฉพาะ ดูคำตอบ
  • ต้องการทำงานกับเขตเวลาเป็นกรณี ๆ ไปในรหัสแอปพลิเคชันของคุณแทนที่จะใช้ทั่วโลกผ่านการตั้งค่าไฟล์กำหนดค่าหรือค่าเริ่มต้น
  • ใช้บริการNTPบนเซิร์ฟเวอร์ทั้งหมด
  • หากใช้FAT32โปรดจำไว้ว่าการประทับเวลาจะถูกเก็บไว้ในเวลาท้องถิ่นไม่ใช่ UTC
  • เมื่อต้องรับมือกับเหตุการณ์ที่เกิดขึ้น (เช่นรายการโทรทัศน์รายสัปดาห์) โปรดจำไว้ว่าเวลาเปลี่ยนแปลงด้วย DST และจะแตกต่างกันตามโซนเวลา
  • สอบถามค่าวันที่และเวลาได้เสมอว่ามีขอบเขตที่ต่ำกว่ารวมถึงขอบเขตพิเศษด้านบน ( >=, <)

ไม่ได้:

  • อย่าสับสน "เขตเวลา" เช่นAmerica/New_Yorkที่มี "เขตเวลาชดเชย" -05:00เช่น พวกเขาเป็นสองสิ่งที่แตกต่างกัน ดูวิกิพีเดียแท็กเขตเวลา
  • อย่าใช้Dateวัตถุของ JavaScript เพื่อทำการคำนวณวันที่และเวลาในเว็บเบราว์เซอร์รุ่นเก่าเนื่องจาก ECMAScript 5.1 และต่ำกว่ามีข้อบกพร่องด้านการออกแบบที่อาจใช้การปรับเวลาตามฤดูกาลอย่างไม่ถูกต้อง (สิ่งนี้ได้รับการแก้ไขใน ECMAScript 6/2015)
  • อย่าเชื่อถือนาฬิกาของลูกค้า มันอาจจะไม่ถูกต้องเป็นอย่างดี
  • อย่าบอกให้คนอื่น "ใช้ UTC ทุกแห่ง" คำแนะนำทั่วไปนี้ย่อมาจากสถานการณ์ที่ถูกต้องหลายประการซึ่งอธิบายไว้ก่อนหน้าในเอกสารนี้ ให้ใช้การอ้างอิงเวลาที่เหมาะสมแทนข้อมูลที่คุณกำลังทำงานด้วย (การประทับเวลาสามารถใช้ UTC ได้ แต่ไม่ควรใช้การกำหนดเวลาในอนาคตและค่าวันที่อย่างเดียว)

การทดสอบ:

  • เมื่อทำการทดสอบตรวจสอบให้แน่ใจว่าคุณทดสอบประเทศในซีกโลกตะวันตกตะวันออกเหนือและใต้ (อันที่จริงในแต่ละไตรมาสของโลกดังนั้น 4 ภูมิภาค) โดยมี DST ทั้งสองอยู่ระหว่างดำเนินการและไม่ (ให้ 8) และเป็นประเทศที่ ไม่ใช้ DST (อีก 4 เพื่อครอบคลุมทุกภูมิภาครวมเป็น 12)
  • ทดสอบการเปลี่ยน DST นั่นคือเมื่อคุณอยู่ในช่วงฤดูร้อนให้เลือกค่าเวลาจากฤดูหนาว
  • ทดสอบกรณีขอบเขตเช่นเขตเวลาที่เป็น UTC + 12 ด้วย DST ทำให้เวลาท้องถิ่นUTC + 13 ในฤดูร้อนและแม้แต่สถานที่ที่เป็น UTC + 13 ในฤดูหนาว
  • ทดสอบไลบรารีและแอปพลิเคชันของบุคคลที่สามทั้งหมดและตรวจสอบให้แน่ใจว่าพวกเขาจัดการข้อมูลเขตเวลาอย่างถูกต้อง
  • ทดสอบเขตเวลาครึ่งชั่วโมงอย่างน้อย

อ้างอิง:

อื่น ๆ :

  • ล็อบบี้ตัวแทนของคุณเพื่อยุติสิ่งที่น่ารังเกียจนั่นคือ DST เราหวังได้เสมอ ...
  • Lobby สำหรับเวลามาตรฐาน Earth

31
การใช้ GMT ไม่ได้แก้ปัญหาจริงๆคุณยังต้องเข้าใจว่าอะไรคือเดลต้าที่เหมาะสมที่จะนำไปใช้และนี่คือสิ่งที่ความซับซ้อนทั้งหมดอยู่ เดลต้าสามารถซับซ้อนเพื่อตรวจสอบในระบบที่ใช้โดยผู้ใช้ในภูมิภาคต่าง ๆ (ด้วยตารางเวลาสวิตช์ประหยัดแสงที่แตกต่างกัน) หรือในระบบที่แสดงข้อมูลประวัติ / อนาคต
ckarras

10
นี่เป็นเรื่องจริงหากแอปพลิเคชันทั้งหมดที่ต้องทำคือการแสดงเวลาท้องถิ่นปัจจุบัน แต่ถ้าเรามีตัวอย่างเซิร์ฟเวอร์ในออสเตรเลียที่ต้องการแสดงวันที่ / เวลาสำหรับการทำธุรกรรมในแคนาดาเมื่อวันที่ 2 เมษายน 2549 (นี่เป็นปีที่แล้วก่อนที่กฎการเปลี่ยนเวลาออมแสงเปลี่ยนไปในแคนาดา) - คุณมีการโทร OS หรือไม่ ที่สามารถทำได้ DateTime ("2006/04/02 14: 35Z") ToLocalTime () WithDaylightSavingRules ("Canada", 2006)?
ckarras

22
ใช่มีการเรียกใช้ระบบปฏิบัติการใน Windows - SystemTimeToTzSpecificLocation msdn.microsoft.com/en-us/library/ms724949(VS.85).aspx
Michael Madsen

7
@tchrist บางทีถ้าคุณยืนกรานว่าคุณทำได้
Peter Ajtai

16
โปรดจำไว้ว่าการแปลงวันที่ในอนาคต (แม้ในวันพรุ่งนี้) เป็น UTC คุณจะสูญเสียบางสิ่งไป ตัวอย่างเช่นคุณใช้ออฟเซ็ตที่รู้จักเพื่อทำการแปลง แต่เนื่องจากวันที่ในอนาคตมีโอกาสเสมอที่กลุ่มที่ตั้งกฎเหล่านั้นจะเปลี่ยนกฎเหล่านั้น นอกจากนี้ยังเป็นไปไม่ได้ที่จะแปลงวันที่ในอนาคตเป็น UTC เนื่องจากไม่ทราบเวลาออมแสงจนกว่าจะถึงปีนั้น (บางประเทศกำหนดวันที่ทุกปีไม่ใช่ 10+ ปีข้างหน้าหรือขึ้นอยู่กับกฎที่ตั้งไว้)
eselk

319

ฉันไม่แน่ใจว่าฉันสามารถเพิ่มคำตอบข้างต้นได้อย่างไร แต่นี่คือบางจุดจากฉัน:

ประเภทของเวลา

คุณควรพิจารณาถึงสี่ครั้ง:

  1. เวลาของเหตุการณ์: เช่นเวลาที่การแข่งขันกีฬาระหว่างประเทศเกิดขึ้นหรือพิธีราชาภิเษก / ความตาย / ฯลฯ สิ่งนี้ขึ้นอยู่กับเขตเวลาของกิจกรรมและไม่ใช่ของผู้ดู
  2. เวลาทีวี: เช่นรายการทีวีบางรายการออกอากาศเวลา 21.00 น. ตามเวลาทั่วโลก สำคัญเมื่อคิดถึงการเผยแพร่ผลลัพธ์ (เช่น American Idol) บนเว็บไซต์ของคุณ
  3. เวลาสัมพัทธ์: เช่น: คำถามนี้มีการปิดค่าหัวที่เปิดใน 21 ชั่วโมง ง่ายต่อการแสดงผล
  4. เวลาที่เกิดขึ้นประจำ: เช่น: รายการทีวีเปิดทุกวันจันทร์เวลา 21.00 น. แม้ว่าจะมีการเปลี่ยนแปลงเวลา

นอกจากนี้ยังมีเวลาในประวัติศาสตร์ / ทางเลือก สิ่งเหล่านี้น่ารำคาญเพราะอาจไม่กลับไปเป็นเวลามาตรฐาน เช่นวันที่ Julian วันที่ตามปฏิทินจันทรคติใน Saturn, The Klingon calendar

การจัดเก็บการประทับเวลาเริ่มต้น / สิ้นสุดใน UTC ทำงานได้ดี สำหรับ 1 คุณต้องมีชื่อเขตเวลาของเหตุการณ์ + ออฟเซ็ตที่จัดเก็บพร้อมกับกิจกรรม สำหรับ 2 คุณต้องใช้ตัวระบุเวลาท้องถิ่นที่เก็บไว้ในแต่ละภูมิภาคและชื่อเขตเวลาท้องถิ่น + ออฟเซ็ตที่เก็บไว้สำหรับผู้ดูทุกคน (เป็นไปได้ที่จะได้รับสิ่งนี้จาก IP หากคุณอยู่ในช่วงวิกฤติ) สำหรับ 3 เก็บใน UTC วินาทีและไม่จำเป็นต้องใช้เขตเวลา 4 เป็นกรณีพิเศษของ 1 หรือ 2 ขึ้นอยู่กับว่ามันเป็นเหตุการณ์ทั่วโลกหรือในท้องถิ่น แต่คุณยังต้องจัดเก็บที่สร้างขึ้นในเวลาประทับเพื่อให้คุณสามารถบอกได้ว่าการกำหนดเขตเวลาเปลี่ยนก่อนหรือหลังเหตุการณ์นี้ถูกสร้างขึ้น นี่เป็นสิ่งจำเป็นหากคุณต้องการแสดงข้อมูลในอดีต

การจัดเก็บครั้ง

  • เก็บเวลาใน UTC ทุกครั้ง
  • แปลงเป็นเวลาท้องถิ่นบนจอแสดงผล (ผู้ใช้กำลังดูข้อมูลในท้องถิ่น)
  • เมื่อจัดเก็บเขตเวลาคุณต้องใช้ชื่อเวลาและการชดเชย นี่เป็นสิ่งจำเป็นเนื่องจากบางครั้งรัฐบาลเปลี่ยนความหมายของเขตเวลา (เช่น: รัฐบาลสหรัฐเปลี่ยนวันที่ DST) และใบสมัครของคุณต้องจัดการกับสิ่งต่าง ๆ อย่างสง่างาม ... เช่น: บันทึกเวลาที่แน่นอนเมื่อตอนของ LOST แสดงทั้งก่อนและหลังกฎ DST การเปลี่ยนแปลง

ออฟเซ็ตและชื่อ

ตัวอย่างของข้างต้นจะเป็น:

เกมการแข่งขันฟุตบอลโลกรอบชิงชนะเลิศเกิดขึ้นที่แอฟริกาใต้ (UTC + 2 - SAST) เมื่อวันที่ 11 กรกฎาคม 2010 เวลา 19:00 UTC

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

เวลาของระบบ

คุณต้องทำให้ OS, ฐานข้อมูลและไฟล์ tzdata ของแอปพลิเคชันตรงกันทั้งคู่และส่วนอื่น ๆ ของโลกและทำการทดสอบอย่างกว้างขวางเมื่อคุณอัพเกรด ไม่เคยได้ยินมาก่อนว่าแอปของบุคคลที่สามที่คุณพึ่งพาไม่ได้จัดการกับการเปลี่ยนแปลง TZ อย่างถูกต้อง

ตรวจสอบให้แน่ใจว่านาฬิกาของฮาร์ดแวร์ถูกตั้งค่าเป็น UTC และหากคุณใช้เซิร์ฟเวอร์ทั่วโลกตรวจสอบให้แน่ใจว่า OS ของพวกเขาได้รับการกำหนดค่าให้ใช้ UTC เช่นกัน สิ่งนี้จะปรากฏขึ้นอย่างชัดเจนเมื่อคุณต้องการคัดลอกไฟล์ apache ที่ถูกหมุนเวียนรายชั่วโมงจากเซิร์ฟเวอร์ในหลายเขตเวลา การจัดเรียงไฟล์ด้วยชื่อไฟล์จะใช้งานได้ต่อเมื่อไฟล์ทั้งหมดถูกตั้งชื่อด้วยเขตเวลาเดียวกัน นอกจากนี้ยังหมายความว่าคุณไม่ต้องทำเลขทางคณิตศาสตร์ในหัวเมื่อคุณ ssh จากกล่องหนึ่งไปยังอีกกล่องหนึ่งและจำเป็นต้องเปรียบเทียบการประทับเวลา

นอกจากนี้ให้เรียกใช้ ntpd บนกล่องทั้งหมด

ลูกค้า

อย่าเชื่อถือการประทับเวลาที่คุณได้รับจากเครื่องไคลเอนต์ว่าถูกต้อง ตัวอย่างเช่นวันที่: ส่วนหัว HTTP หรือการDate.getTime()โทรจาวาสคริปต์ สิ่งเหล่านี้ใช้ได้เมื่อใช้เป็นตัวระบุทึบแสงหรือเมื่อทำคณิตศาสตร์วันที่ระหว่างเซสชันเดียวในไคลเอนต์เดียวกัน แต่อย่าพยายามอ้างอิงค่าเหล่านี้กับสิ่งที่คุณมีบนเซิร์ฟเวอร์ ลูกค้าของคุณไม่ได้ใช้ NTP และอาจไม่จำเป็นต้องมีแบตเตอรี่ที่ใช้งานได้สำหรับนาฬิกา BIOS ของพวกเขา

เรื่องไม่สำคัญ

ในที่สุดรัฐบาลบางครั้งจะทำสิ่งที่แปลกมาก:

เวลามาตรฐานในเนเธอร์แลนด์คือ 19 นาทีและ 32.13 วินาทีก่อนเวลา UTC ตามกฎหมายจาก 1909-05-01 ถึง 1937-06-30 เขตเวลานี้ไม่สามารถแสดงได้อย่างแน่นอนโดยใช้รูปแบบ HH: MM

ตกลงฉันคิดว่าฉันทำเสร็จแล้ว


6
คำตอบนี้มีจุดยอดเยี่ยมโดยเฉพาะอย่างยิ่งฉันต้องการที่จะชี้ให้เห็นส่วนนี้ "เวลาที่เกิดซ้ำ: เช่น: รายการทีวีเปิดทุกวันจันทร์เวลา 21.00 น. ถึงแม้จะมีการเปลี่ยนแปลง DST" การจัดเก็บเวลาใน UTC ในฐานข้อมูล มีแง่มุมมากมายในการจัดการกับเขตเวลา อย่างไรก็ตามการจัดการ "เหตุการณ์ที่เกิดขึ้นซ้ำ ๆ " ซึ่งข้ามสิ่งกีดขวาง DST นั้นรุนแรงมาก
Jared Hales

45
+1 สำหรับ Trivia การรักษาที่น่าสนใจเนื้อหาที่ทำให้งานนี้สนุกมากขึ้นซึ่งอาจนำไปสู่การผลิตที่เพิ่มขึ้น :)
คริส

4
มีหลายสิ่งที่ดีในคำตอบนี้ แต่มีปัญหาเล็กน้อย 1) ตัวย่อโซนเวลาหลายตัวมีความคลุมเครือ ดูที่นี่ 2) ไม่ได้เสมอคุณต้องการที่จะเก็บใน UTC ส่วนใหญ่เวลา - ใช่ แต่บริบทมีความสำคัญ ตามเงื่อนไขของคุณเวลาโทรทัศน์จะไม่ถูกจัดเก็บใน UTC นอกจากนี้บางครั้งมันผิดกฎหมายหรือขัดต่อนโยบายที่จะไม่เก็บเวลาท้องถิ่น - ซึ่งเป็นสิ่งที่DateTimeOffsetมีประโยชน์เช่น(หรือเทียบเท่า) มิฉะนั้นเขียนดี
Matt Johnson-Pint

1
ดังนั้นทุกคนยอมรับว่าห้องสมุด Joda เป็นเครื่องมือที่ดีที่สุดสำหรับงาน อย่างไรก็ตามเราจำเป็นต้องอัปเดต (สร้างใหม่) ไฟล์ JODA jar ตามบทความนี้ ( joda.org/joda-time/tz_update.html ) เพื่อให้ทันกับข้อมูลเขตเวลาล่าสุด มีวิธีมาตรฐานในการดาวน์โหลดข้อมูลเขตเวลาล่าสุดจากเว็บไซต์ IANA ( iana.org/time-zones ) และสร้างห้องสมุดjodaใหม่หรือไม่? กล่าวอีกนัยหนึ่งเป็นไปได้ไหมที่จะทำให้กระบวนการนี้เป็นแบบอัตโนมัติแทนที่จะทำด้วยตนเอง
saravana_pc

2
เรื่องไม่สำคัญของเนเธอร์แลนด์ดูน่าเชื่อถือ ietf.org/rfc/rfc3339.txtมาตรา 5.8 ครึ่งทางคิดว่ามีคนดึงขาของเรา
ruffin

89

นี่เป็นปัญหาที่สำคัญและยากอย่างน่าประหลาดใจ ความจริงก็คือว่าไม่มีมาตรฐานที่น่าพอใจอย่างสมบูรณ์สำหรับเวลาที่คงอยู่ ตัวอย่างเช่นมาตรฐาน SQL และรูปแบบ ISO (ISO 8601) ไม่ชัดเจนเพียงพอ

จากมุมมองแนวคิดหนึ่งมักเกี่ยวข้องกับข้อมูลวันที่สองประเภทและสะดวกในการแยกความแตกต่าง (มาตรฐานด้านบนไม่ได้): " เวลาทางกายภาพ " และ " เวลาทางแพ่ง "

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

เวลา "แพ่ง" เป็นข้อมูลจำเพาะของวันที่และเวลาซึ่งปฏิบัติตามบรรทัดฐานทางแพ่ง: เวลาที่นี่ถูกระบุอย่างสมบูรณ์โดยชุดของเขตข้อมูลวันที่ (Y, M, D, H, MM, S, FS) และ TZ (ข้อกำหนดเขตเวลา) (เช่นกัน "ปฏิทิน" จริง ๆ แล้ว แต่ให้ถือว่าเรา จำกัด การสนทนากับปฏิทินเกรโกเรียนเท่านั้น) เขตเวลาและปฏิทินร่วมกันอนุญาตให้ (ในหลักการ) แผนที่จากตัวแทนหนึ่งไปยังอีก แต่ช่วงเวลาทางแพ่งและทางกายภาพนั้นเป็นประเภทที่แตกต่างกันโดยพื้นฐานและพวกเขาควรจะแยกแนวคิดและการรักษาที่แตกต่างกัน (การเปรียบเทียบ: อาร์เรย์ของไบต์และสายอักขระ)

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

จอห์นบันทึกในปฏิทินของเขาเตือนสำหรับเหตุการณ์บางอย่างที่ datetime 2019-Jul-27, 10:30:00, TZ = Chile/Santiago, (ซึ่งได้ชดเชย GMT-4 ดังนั้นจึงสอดคล้องกับ UTC 2019-Jul-27 14:30:00) แต่บางวันในอนาคตประเทศตัดสินใจเปลี่ยน TZ offset เป็น GMT-5

ตอนนี้เมื่อวันที่มาถึง ... ควรเตือนความทรงจำที่

A) 2019-Jul-27 10:30:00 Chile/Santiago = UTC time 2019-Jul-27 15:30:00?

หรือ

B) 2019-Jul-27 9:30:00 Chile/Santiago = UTC time 2019-Jul-27 14:30:00?

ไม่มีคำตอบที่ถูกต้องเว้นแต่ว่าใครจะรู้ว่าจอห์นหมายถึงความหมายเมื่อเขาบอกปฏิทิน "โปรดโทรหาฉันที่2019-Jul-27, 10:30:00 TZ=Chile/Santiago"

เขาหมายถึง "วันเวลาพลเรือน" ("เมื่อนาฬิกาในเมืองของฉันบอกเวลา 10:30 น.") หรือไม่ ในกรณีนั้น A) เป็นคำตอบที่ถูกต้อง

หรือเขาหมายถึง "ร่างกายทันใจทันเวลา" ซึ่งเป็นจุดในช่วงเวลาต่อเนื่องของเอกภพของเราพูดว่า "เมื่อสุริยุปราคาต่อไปเกิดขึ้น" ในกรณีนั้นคำตอบ B) นั้นถูกต้อง

API วันที่ / เวลาไม่กี่ครั้งจะได้รับการแยกความแตกต่างนี้: Jodatimeซึ่งเป็นรากฐานของ Java DateTime API ถัดไป (ที่สาม!) (JSR 310)


1
อีกประเด็นที่ควรพิจารณาซึ่งฉันไม่ได้เห็นใน API คือแม้ว่าจะให้เวลาและเขตเวลา แต่ก็มีความหมายที่เป็นไปได้อย่างน้อยสองตัวอย่างเช่น "13: 00: 00EDT" มันอาจหมายถึงสิ่งที่เป็นที่ทราบกันว่าเกิดขึ้นในเวลา 13.00 น. ตามเวลาท้องถิ่นซึ่งเชื่อกันว่าเป็นเวลาตามฤดูกาลของภาคตะวันออก ได้เกิดขึ้นในสถานที่ที่สังเกตเวลาตามฤดูกาลของภาคตะวันออก หากมีการประทับเวลาหลายครั้งที่ข้อมูลเขตเวลาอาจผิด (เช่นไฟล์กล้องดิจิทัล) ...
supercat

1
... การรู้ว่าพวกเขาสะท้อนเวลาท้องถิ่นที่ถูกต้องหรือเวลาทั่วโลกอาจมีความสำคัญในการพิจารณาว่าจะแก้ไขอย่างไร
supercat

3
เห็นได้ชัดว่าจอห์นต้องการก) เพราะผู้คนไปทำงานเวลา 8:30 น. ไม่ว่า DST หรือเขตเวลาใดในขณะนี้ หากพวกเขาเข้าสู่ DST พวกเขาจะไปทำงานเวลา 8:30 น. เมื่อพวกเขาออกจาก DST พวกเขาจะไปทำงานที่ 8:30 หากประเทศตัดสินใจย้ายไปยังเขตเวลาอื่นพวกเขาจะไปทำงานในเวลา 8.30 น.
Gianluca Ghettini

59

สร้างการแยกข้อกังวลทางสถาปัตยกรรมที่ชัดเจน - เพื่อทราบว่าระดับการโต้ตอบกับผู้ใช้และต้องเปลี่ยนวันที่เวลาสำหรับ / จากการรับรองแบบบัญญัติ (UTC) ไม่ใช่วันที่เวลา UTC เป็นการนำเสนอ (ตามเขตเวลาท้องถิ่นของผู้ใช้) เวลา UTC เป็นรูปแบบ (ยังคงไม่ซ้ำกันสำหรับส่วนหลังและระดับกลาง)

นอกจากนี้ให้ตัดสินใจว่าผู้ชมที่แท้จริงของคุณคืออะไรคุณไม่ต้องรับใช้และคุณวาดเส้นที่ไหน อย่าแตะต้องปฏิทินที่แปลกใหม่เว้นแต่คุณจะมีลูกค้าสำคัญอยู่ที่นั่นแล้วพิจารณาแยกเซิร์ฟเวอร์ที่ต้องเผชิญกับผู้ใช้เฉพาะสำหรับภูมิภาคนั้น

หากคุณสามารถได้รับและรักษาตำแหน่งของผู้ใช้ให้ใช้ตำแหน่งสำหรับการแปลงวันที่และเวลาอย่างเป็นระบบ (พูด. NET วัฒนธรรมหรือตาราง SQL) แต่เป็นวิธีสำหรับผู้ใช้ปลายทางในการเลือกการแทนที่หากวันที่มีความสำคัญสำหรับผู้ใช้ของคุณ

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

กำหนดเขตเวลาอ้างอิงเวลาสำหรับข้อมูลที่มาในรูปแบบจำนวนมากเช่นไฟล์บริการบนเว็บ ฯลฯ บริษัท East Coast มีศูนย์ข้อมูลใน CA - คุณต้องถามและรู้ว่าสิ่งที่พวกเขาใช้เป็นมาตรฐานแทนที่จะเป็นหนึ่งหรืออื่น ๆ

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


40

คุณจำเป็นต้องรู้เกี่ยวกับโอลสันฐานข้อมูล TZซึ่งสามารถใช้ได้จากftp://elsie.nci.nih.gov/pub http://iana.org/time-zones/ มีการอัปเดตหลายครั้งต่อปีเพื่อจัดการกับการเปลี่ยนแปลงในนาทีสุดท้ายของเวลา (และไม่ว่า) เพื่อสลับระหว่างเวลาฤดูหนาวและฤดูร้อน (เวลามาตรฐานและการปรับเวลาตามฤดูกาล) ในประเทศต่างๆทั่วโลก ในปี 2009 รุ่นล่าสุดคือปี 2009; ในปี 2010 มันคือ 2010n; ในปี 2011 มันคือ 2011n; ณ สิ้นเดือนพฤษภาคม 2555 มีการเปิดตัวปี 2555c โปรดทราบว่ามีชุดของรหัสในการจัดการข้อมูลและข้อมูลเขตเวลาจริงด้วยตัวเองในไฟล์เก็บถาวรสองชุด (tzcode20xxy.tar.gz และ tzdata20xxy.tar.gz) ทั้งรหัสและข้อมูลอยู่ในโดเมนสาธารณะ

นี่คือที่มาของชื่อเขตเวลาเช่น America / Los_Angeles (และคำพ้องความหมายเช่น US / Pacific)

หากคุณต้องการติดตามโซนต่าง ๆ คุณต้องใช้ฐานข้อมูล Olson ตามที่คนอื่นได้แนะนำคุณยังต้องการจัดเก็บข้อมูลในรูปแบบคงที่ - UTC เป็นปกติที่เลือก - พร้อมกับบันทึกเขตเวลาที่ข้อมูลถูกสร้างขึ้น คุณอาจต้องการแยกความแตกต่างระหว่างออฟเซ็ตจาก UTC ในเวลาและชื่อโซนเวลา ที่สามารถสร้างความแตกต่างในภายหลัง นอกจากนี้การทราบว่าขณะนี้ 2010-03-28T23: 47: 00-07: 00 (US / Pacific) อาจหรือไม่อาจช่วยคุณแปลค่า 2010-11-15T12: 30 ซึ่งระบุไว้ใน PST ( เวลามาตรฐานแปซิฟิก) มากกว่า PDT (เวลาออมแสงแปซิฟิก)

อินเตอร์เฟสไลบรารี C มาตรฐานไม่เป็นประโยชน์อย่างมากกับสิ่งต่างๆ


ข้อมูล Olson ได้ถูกย้ายส่วนหนึ่งเป็นเพราะ AD Olson กำลังจะออกในเร็ว ๆ นี้และส่วนหนึ่งเป็นเพราะมีการฟ้องร้องทางกฎหมายกับผู้ดูแลรักษาเนื่องจากการละเมิดลิขสิทธิ์ ฐานข้อมูลเขตเวลามีการจัดการในขณะนี้ภายใต้การอุปถัมภ์ของIANA , Internet ได้กำหนดหมายเลขผู้มีอำนาจและมีการเชื่อมโยงในหน้าไปยัง'โซนเวลาฐานข้อมูล' รายชื่อผู้รับจดหมายการอภิปรายอยู่ในขณะนี้tz@iana.org; tz-announce@iana.orgรายการประกาศเป็น


12
ฐานข้อมูล Olson มีข้อมูลประวัติเช่นกันซึ่งทำให้เป็นประโยชน์อย่างยิ่งสำหรับการจัดการ DST เช่นจะรู้ว่าค่า UTC ที่ตรงกับ 31 มีนาคม 2000 ในสหรัฐอเมริกาไม่ได้อยู่ใน DST แต่เป็นค่า UTC ที่ตรงกับ 31 มีนาคม 2008 ในสหรัฐอเมริกาคือ
Josh Kelley

3
The Unicode Consortium จะทำการจับคู่ระหว่าง Olson tome zone ID และ Windows time IDs: unicode.org/repos/cldr-tmp/trunk/diff/supplemental/ …
Josh Kelley

ลิงค์อัปเดตสำหรับหน้าของ Unicode Consortium: unicode.org/repos/cldr-tmp/trunk/diff/supplemental/…
ช่วง

เราสามารถหาข้อมูลเกี่ยวกับการแยกวิเคราะห์ไฟล์ Olson ได้ที่ไหน? ฉันต้องการรวบรวมมันลงในตาราง db แต่ไม่สามารถคิดออกว่าฉันควรอ่านไฟล์อย่างไร
shealtiel

@gidireich: พบข้อมูลหลักกับข้อมูลและไม่ง่ายที่จะเข้าใจ เอกสารหลักของมันอยู่ในzic.8man page (หรือzic.8.txt) คุณจะต้องใช้tzcode2011i.tar.gzไฟล์มากกว่าหรือtzdata2011i.tar.gzเพื่อรับข้อมูลนี้
Jonathan Leffler

26

โดยทั่วไปให้รวมการชดเชยเวลาท้องถิ่น (รวมถึงการชดเชย DST)ในการประทับเวลาที่เก็บไว้: UTC เพียงอย่างเดียวไม่เพียงพอหากคุณต้องการแสดงการประทับเวลาในโซนเวลาดั้งเดิม (และการตั้งค่า DST) ในภายหลัง

โปรดทราบว่าการชดเชยไม่ได้เป็นจำนวนเต็มตลอดเวลา (เช่นเวลามาตรฐานของอินเดียคือ UTC + 05: 30)

ตัวอย่างเช่นรูปแบบที่เหมาะสมเป็น tuple (เวลายูนิกซ์ชดเชยในนาที) หรือISO 8601


5
สำหรับการแสดงผลออฟเซตนั้นสมบูรณ์แบบ หากคุณต้องการเปลี่ยนแปลงการชดเชยก็ยังไม่เพียงพอ คุณต้องทราบเขตเวลาด้วยเนื่องจากค่าใหม่อาจต้องการการชดเชยที่แตกต่างกัน
Matt Johnson-Pint

23

การข้ามขอบเขตของ "เวลาคอมพิวเตอร์" และ "เวลาของผู้คน" เป็นฝันร้าย หลักสำคัญคือไม่มีมาตรฐานสำหรับกฎที่ควบคุมเขตเวลาและเวลาออมแสง ประเทศต่างๆสามารถเปลี่ยนแปลงเขตเวลาและกฎ DST ได้ตลอดเวลาและทำได้

บางประเทศเช่นอิสราเอลบราซิลตัดสินใจในแต่ละปีว่าจะมีการปรับเวลาตามฤดูกาลดังนั้นจึงเป็นไปไม่ได้ที่จะรู้ล่วงหน้าว่าเมื่อใด (ถ้า) DST จะมีผล คนอื่น ๆ ได้แก้ไขกฎ (ish) ว่าเมื่อ DST มีผลบังคับใช้ ประเทศอื่น ๆ ไม่ได้ใช้ DST เป็นทั้งหมด

เขตเวลาไม่จำเป็นต้องเป็นข้อแตกต่างชั่วโมงเต็มจาก GMT เนปาลคือ +5.45 มีเขตเวลาแม้กระทั่งที่เป็น +13 นั่นหมายความว่า:

SUN 23:00 in Howland Island (-12)
MON 11:00 GMT 
TUE 00:00 in Tonga (+13)

มีทั้งหมดในเวลาเดียวกัน แต่ 3 วันที่แตกต่างกัน!

นอกจากนี้ยังไม่มีมาตรฐานที่ชัดเจนเกี่ยวกับตัวย่อของเขตเวลาและวิธีที่พวกเขาเปลี่ยนแปลงเมื่ออยู่ใน DST ดังนั้นคุณจะได้สิ่งต่าง ๆ ดังนี้:

AST Arab Standard Time     UTC+03
AST Arabian Standard Time  UTC+04
AST Arabic Standard Time   UTC+03

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

เมื่อทำการทดสอบตรวจสอบให้แน่ใจว่าคุณทดสอบประเทศในซีกโลกตะวันตกและตะวันออกโดยมีทั้ง DST อยู่ระหว่างดำเนินการและไม่ใช่และเป็นประเทศที่ไม่ได้ใช้ DST (รวม 6 รายการ)


เกี่ยวกับอิสราเอล - นี่เป็นเรื่องจริงครึ่งหนึ่ง แม้ว่าเวลาสำหรับการเปลี่ยนแปลง DST ไม่ใช่วันที่ที่ระบุในปฏิทินจูเลียน แต่มีกฎตามปฏิทินฮีบรู (มีการเปลี่ยนแปลงในปี 2014) อย่างไรก็ตามแนวคิดทั่วไปถูกต้อง - สิ่งนี้อาจเปลี่ยนแปลงได้บ้างในบางครั้ง
Yaron U.

1
นอกจากนี้ AST = เวลามาตรฐานแอตแลนติก สำหรับ 'คำแนะนำที่ดีที่สุด' มันก็โอเคเป็นจุดเริ่มต้น แต่คุณต้องอ่านส่วนที่เหลือของหน้านี้และพูดคำอธิษฐานเล็กน้อยและคุณอาจทำให้ถูกต้องสักระยะหนึ่ง
DavidWalley

20

สำหรับ PHP:

คลาส DateTimeZone ใน PHP> 5.2 มีพื้นฐานมาจาก Olson DB ที่คนอื่นพูดถึงดังนั้นหากคุณทำการแปลงเขตเวลาใน PHP และไม่ใช่ใน DB คุณจะได้รับการยกเว้นในการทำงานกับไฟล์ Olson (ที่เข้าใจได้ยาก)

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

เพื่อรับมือกับปัญหาดังกล่าวให้ใช้แพคเกจ PECL timezonedb หน้าที่ของมันคือการอัพเดทข้อมูลเขตเวลาของ PHP ติดตั้งแพคเกจนี้บ่อยเท่าที่มีการปรับปรุง (ฉันไม่แน่ใจว่าการอัปเดตของแพคเกจนี้เป็นไปตามการอัปเดตของ Olson หรือไม่ แต่ดูเหมือนว่าจะได้รับการอัปเดตที่ความถี่อย่างน้อยใกล้เคียงกับความถี่ของการอัปเดต Olson มากขึ้น)


18

หากการออกแบบของคุณสามารถรองรับได้ให้หลีกเลี่ยงการแปลงเวลาท้องถิ่นทั้งหมดด้วยกัน!

ฉันรู้ว่าบางอย่างนี้อาจฟังดูบ้า แต่ลองนึกถึง UX: กระบวนการผู้ใช้ใกล้วันที่สัมพัทธ์ (วันนี้เมื่อวานวันจันทร์ถัดไปวันจันทร์) เร็วกว่าวันที่สัมบูรณ์ (2010.09.17 วันศุกร์ที่ 17 กันยายน) และเมื่อคุณคิดถึงมันมากขึ้นความแม่นยำของเขตเวลา (และ DST) มีความสำคัญยิ่งใกล้กับวันที่now()ดังนั้นถ้าคุณสามารถแสดงวันที่ / วันที่ในรูปแบบสัมพัทธ์สำหรับ +/- 1 หรือ 2 สัปดาห์ส่วนที่เหลือของ วันที่สามารถ UTC และมันไม่สำคัญมากถึง 95% ของผู้ใช้

วิธีนี้คุณสามารถเก็บวันที่ทั้งหมดใน UTC และทำการเปรียบเทียบแบบเปรียบเทียบใน UTC และเพียงแสดงวันที่ผู้ใช้ UTC นอกเกณฑ์วันที่ที่เกี่ยวข้องของคุณ

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


16

ในขณะที่ฉันยังไม่ได้ลองวิธีการปรับเปลี่ยนเขตเวลาฉันจะพบว่าน่าสนใจเป็นดังนี้:

  1. เก็บทุกอย่างใน UTC

  2. สร้างตารางที่TZOffsetsมีสามคอลัมน์: RegionClassId, StartDateTime และ OffsetMinutes (int ในหน่วยนาที)

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

เมื่อคุณต้องการคำนวณเวลาท้องถิ่นของเวลา UTC เพียงทำสิ่งนี้:

SELECT DATEADD('m', SUM(OffsetMinutes), @inputdatetime) AS LocalDateTime
FROM   TZOffsets
WHERE  StartDateTime <= @inputdatetime
       AND RegionClassId = @RegionClassId;

คุณอาจต้องการแคชตารางนี้ในแอพของคุณและใช้ LINQ หรือวิธีที่คล้ายกันในการทำแบบสอบถามแทนที่จะกดปุ่มฐานข้อมูล

ข้อมูลนี้สามารถกลั่นจากฐานข้อมูล TZ โดเมนสาธารณะ

ข้อดีและเชิงอรรถของวิธีการนี้:

  1. ไม่มีกฎถูกอบเป็นรหัสคุณสามารถปรับออฟเซ็ตสำหรับภูมิภาคใหม่หรือช่วงวันที่ได้อย่างง่ายดาย
  2. คุณไม่จำเป็นต้องสนับสนุนทุกช่วงวันที่หรือภูมิภาคคุณสามารถเพิ่มได้ตามต้องการ
  3. ภูมิภาคไม่จำเป็นต้องตรงกับเขตแดนทางภูมิศาสตร์โดยตรงและเพื่อหลีกเลี่ยงการทำซ้ำแถว (เช่นรัฐส่วนใหญ่ในสหรัฐฯจัดการ DST ด้วยวิธีเดียวกัน) คุณสามารถมีรายการ RegionClass แบบกว้างที่เชื่อมโยงในตารางอื่นไปยังรายการแบบดั้งเดิมอื่น ๆ ของ รัฐประเทศ ฯลฯ
  4. สำหรับสถานการณ์เช่นสหรัฐอเมริกาซึ่งวันที่เริ่มต้นและสิ้นสุดของ DST มีการเปลี่ยนแปลงในช่วงไม่กี่ปีที่ผ่านมานี่เป็นเรื่องง่ายที่จะจัดการ
  5. เนื่องจากเขตข้อมูล StartDateTime สามารถเก็บเวลาได้เช่นกันการจัดการเวลามาตรฐานเปลี่ยนแปลง 2:00 AM จึงเป็นเรื่องง่าย
  6. ไม่ใช่ทุกที่ในโลกที่ใช้ DST 1 ชั่วโมง นี้จัดการกรณีเหล่านั้นได้อย่างง่ายดาย
  7. ตารางข้อมูลเป็นข้ามแพลตฟอร์มและอาจเป็นโครงการโอเพ่นซอร์สแยกต่างหากที่นักพัฒนาซอฟต์แวร์สามารถใช้เกือบทุกแพลตฟอร์มฐานข้อมูลหรือภาษาโปรแกรม
  8. สิ่งนี้สามารถใช้สำหรับการชดเชยที่ไม่มีส่วนเกี่ยวข้องกับเขตเวลา ตัวอย่างเช่นการปรับ 1 วินาทีที่เกิดขึ้นเป็นครั้งคราวเพื่อปรับสำหรับการหมุนของโลก, การปรับประวัติและภายในปฏิทินเกรโกเรียน ฯลฯ
  9. เนื่องจากสิ่งนี้อยู่ในตารางฐานข้อมูลแบบสอบถามรายงานมาตรฐานเป็นต้นสามารถใช้ประโยชน์จากข้อมูลโดยไม่ต้องเดินทางผ่านรหัสตรรกะทางธุรกิจ
  10. การดำเนินการนี้จะจัดการกับการชดเชยเวลาในเขตเวลาเช่นกันหากคุณต้องการและยังสามารถอธิบายกรณีที่เกิดขึ้นในอดีตที่มีการกำหนดภูมิภาคให้กับเขตเวลาอื่น สิ่งที่คุณต้องมีคือวันที่เริ่มต้นที่กำหนดเขตเวลาให้กับแต่ละภูมิภาคด้วยวันที่เริ่มต้นที่น้อยที่สุด สิ่งนี้จะต้องมีการสร้างอย่างน้อยหนึ่งภูมิภาคสำหรับแต่ละเขตเวลา แต่จะอนุญาตให้คุณถามคำถามที่น่าสนใจเช่น: "ความแตกต่างของเวลาท้องถิ่นระหว่าง Yuma, Arizona และ Seattle, Washington เมื่อวันที่ 2 กุมภาพันธ์ 1989 เวลา 5:00 น." (เพียงลบหนึ่ง SUM () จากอีกอันหนึ่ง)

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


8
แนวคิดฐานข้อมูลของคุณถูกนำไปใช้เป็นฐานข้อมูล Olson แล้ว ในขณะที่การปรับเวลาตามฤดูกาลสร้างการทับซ้อนที่ระบุเขตเวลาที่เฉพาะเจาะจงของเวลากลางวันสามารถช่วยแก้ไขปัญหาได้ 2:15 EST และ 2:15 EDT นั้นแตกต่างกัน ตามที่ระบุในโพสต์อื่น ๆ ที่ระบุออฟเซ็ตยังช่วยแก้ไขความคลุมเครือ
BillThor

5
ปัญหาใหญ่ในการรักษาฐานข้อมูลของคุณคือทำให้มันอัพเดทอยู่เสมอ Olson และ Windows ได้รับการดูแลสำหรับคุณ ฉันมีมากกว่าหนึ่งกรณีที่มีการเปลี่ยน DST ไม่ถูกต้องเนื่องจากตารางล้าสมัย การริปออกมาทั้งหมดและอาศัยเฟรมเวิร์กหรือฐานข้อมูลระดับ OS นั้นมีความน่าเชื่อถือมากกว่า
Matt Johnson-Pint

4
อย่าสร้างฐานข้อมูลของคุณเอง : พึ่งพา API ของระบบเสมอ!
อเล็กซ์

15

ฉันเพิ่งมีปัญหาในเว็บแอปพลิเคชันที่ Ajax โพสต์แบ็กดาต้าแบ็กกลับมาที่โค้ดฝั่งเซิร์ฟเวอร์ของฉันแตกต่างจากดาต้าไทม์ที่ให้บริการ

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

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

การเรียนรู้ของฉันจากสิ่งนี้: อย่าใช้การคำนวณวันที่และเวลาของ JavaScript ในเว็บแอปพลิเคชันเว้นแต่คุณจะต้อง


Javascript ทำงานที่เครื่องไคลเอ็นต์ไม่ใช่ที่เครื่องเซิร์ฟเวอร์ Javascript พื้นฐานของ Javascript เป็นวันที่และเวลาของลูกค้าไม่ใช่วันที่และเวลาของเซิร์ฟเวอร์
BalusC

สวัสดี BalusC ฉันเข้าใจสิ่งนี้ (จากโพสต์ต้นฉบับของฉัน: "สคริปต์ javacode บนไคลเอนต์ที่สร้างวันที่ ... ") ปัญหาของฉันคือเครื่องไคลเอนต์บางเครื่องประมวลผล DST ในทางเดียวและอื่น ๆ อีกวิธีหนึ่ง ดังนั้นฉันจึงย้ายการประมวลผลฝั่งเซิร์ฟเวอร์ทั้งหมดเพื่อป้องกันความแปลกประหลาดของเบราว์เซอร์
Joon

@ Joon— และมีข้อบกพร่องในการใช้งานจาวาสคริปต์ที่คุณไม่สามารถตรวจพบหรืออนุญาต ใช่ไม่เคยใช้การคำนวณวันที่ ECMAScript ฝั่งไคลเอ็นต์สำหรับสิ่งที่มีความสำคัญ (แม้ว่าคุณจะสามารถทำงานได้ดีอย่างอื่น)
RobG

14

ฉันได้รับผลกระทบนี้ในสองประเภทของระบบ“ ระบบวางแผนการเปลี่ยน (เช่นคนงานในโรงงาน)” และ“ ระบบการจัดการพึ่งพาก๊าซ) ...

วันที่ยาวนาน 23 และ 25 ชั่วโมงเป็นความเจ็บปวดที่ต้องรับมือดังนั้นการกะ 8 ชั่วโมงที่ใช้เวลา 7 ชั่วโมงหรือ 9 ชั่วโมง ปัญหาคือคุณจะพบว่าลูกค้าแต่ละรายหรือแม้แต่แผนกของลูกค้ามีกฎที่แตกต่างกันที่พวกเขาสร้างขึ้น (มักจะไม่มีเอกสาร) ในสิ่งที่พวกเขาทำในกรณีพิเศษเหล่านี้

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

ฉันคิดว่าในทุกกรณีคุณควรบันทึกเวลาเป็น UTC และแปลงเป็น / จากเวลาท้องถิ่นก่อนที่จะจัดเก็บวันที่ / เวลา อย่างไรก็ตามแม้จะรู้ว่าต้องใช้เวลาในการกำหนดอะไรอาจทำได้ยากด้วยการปรับเวลาตามฤดูกาลและโซนเวลา


6
แฟนสาวของฉันพยาบาลทำงานคืนและพวกเขาต้องเขียนเขตเวลาในระหว่างการเปลี่ยนแปลง DST ตัวอย่างเช่น 2AM CST เทียบกับ CDAM 2AM
Joe Phillips

1
ใช่มันเป็นเรื่องปกติ: เมื่อคุณคำนวณค่าเฉลี่ยรายวัน (แพ่ง) คุณต้องรับมือกับวันที่ 23, 24 หรือ 25 ชั่วโมง ดังนั้นเมื่อคุณคำนวณเพิ่ม 1 วันจะไม่เพิ่ม 24 ชั่วโมง ! ประการที่สองอย่าพยายามสร้างรหัสเขตเวลาของคุณเอง ใช้ระบบ API เท่านั้น และไม่ลืมที่จะปรับปรุงแต่ละระบบที่นำไปใช้ในการสั่งซื้อเพื่อให้ได้ฐานข้อมูลเขตเวลา up-to-วัน
อเล็กซ์

12

สำหรับเว็บกฎนั้นไม่ซับซ้อน ...

  • ฝั่งเซิร์ฟเวอร์ให้ใช้ UTC
  • ฝั่งไคลเอ็นต์ใช้Olson
    • สาเหตุ: UTC-offsets ไม่ใช่การออมในเวลากลางวัน (เช่นนิวยอร์กคือ EST (UTC - 5 ชั่วโมง) ส่วนหนึ่งของปี, EDT (UTC - 4 ชั่วโมง) ส่วนที่เหลือของปี)
    • สำหรับการกำหนดเขตเวลาฝั่งไคลเอ็นต์คุณมีสองตัวเลือก:

ส่วนที่เหลือเป็นเพียงการแปลง UTC / โลคัลโดยใช้ไลบรารี datetime ฝั่งเซิร์ฟเวอร์ของคุณ ดีที่จะไป ...


2
นี่เป็นคำแนะนำที่ดีว่าเป็นจุดเริ่มต้น แต่ทั้งหมดขึ้นอยู่กับแอปพลิเคชัน นี่อาจใช้ได้สำหรับเว็บไซต์ที่เป็นมิตร แต่หากมีด้านกฎหมาย / เขตอำนาจศาล / ด้านการเงินในการสมัครของคุณที่มีคนอาจฟ้อง (ฉันเคยทำงานหลายครั้ง) นี่เป็นเรื่องง่ายเกินไปเพราะมี ' เวลา 'ตามที่ระบุไว้ที่อื่นในหน้านี้
DavidWalley

12

เมื่อพูดถึงแอปพลิเคชันที่ทำงานบนเซิร์ฟเวอร์รวมถึงเว็บไซต์และบริการอื่น ๆ ส่วนท้ายการตั้งค่าโซนเวลาของเซิร์ฟเวอร์ควรถูกละเว้นโดยแอปพลิเคชัน

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

รหัสฝั่งเซิร์ฟเวอร์รวมถึงเว็บไซต์ไม่ควรคาดหวังว่าโซนเวลาท้องถิ่นของเซิร์ฟเวอร์จะเป็นสิ่งใดโดยเฉพาะ

ในบางภาษาเขตเวลาท้องถิ่นสามารถคืบเข้าไปในรหัสแอปพลิเคชันได้อย่างง่ายดาย ตัวอย่างเช่นDateTime.ToUniversalTimeวิธีการใน. NET จะแปลงจากเขตเวลาท้องถิ่นเป็น UTC และDateTime.Nowคุณสมบัติส่งคืนเวลาปัจจุบันในโซนเวลาท้องถิ่น ตัวDateสร้างใน JavaScript ใช้โซนเวลาท้องถิ่นของคอมพิวเตอร์ มีตัวอย่างอื่น ๆ อีกมากมายเช่นนี้ มันเป็นสิ่งสำคัญในการฝึกการเขียนโปรแกรมป้องกันการหลีกเลี่ยงรหัสใด ๆ ที่ใช้การตั้งค่าโซนเวลาท้องถิ่นของคอมพิวเตอร์

จองโดยใช้เขตเวลาท้องถิ่นสำหรับรหัสฝั่งไคลเอ็นต์เช่นแอปพลิเคชันเดสก์ท็อปแอปพลิเคชันมือถือและ JavaScript ฝั่งไคลเอ็นต์


11

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

UTC หลีกเลี่ยงปัญหาการปรับเวลาตามฤดูกาลและเซิร์ฟเวอร์ที่ไม่ซิงค์กันอาจทำให้เกิดผลลัพธ์ที่ไม่คาดคิดซึ่งใช้เวลาสักครู่ในการวินิจฉัย


9

ระวังเมื่อจัดการกับการประทับเวลาที่เก็บไว้ในระบบไฟล์ FAT32 - มันจะยังคงอยู่ในพิกัดเวลาท้องถิ่น (ซึ่งรวมถึง DST - ดูบทความ msdn ) โดนเผาไปแล้ว


จุดที่ดี NTFS ไม่มีปัญหานี้ แต่บางคนยังคงใช้ FAT32 - โดยเฉพาะในคีย์ USB
Matt Johnson-Pint

7

อีกอย่างหนึ่งตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์มีการใช้โปรแกรมปรับปรุงการออมตามฤดูกาลที่ทันสมัย

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

ปรากฎว่าในท้ายที่สุดมันก็คือเซิร์ฟเวอร์ พวกเขาต้องการโปรแกรมปรับปรุงที่ใช้งานล่าสุด ( Windows Server 2003 )


6

DateTimeZone::listAbbreviations()ผลลัพธ์ของ PHP

วิธีการ PHP นี้จะคืนค่าอาเรย์แบบเชื่อมโยงที่มีเขตเวลา 'หลัก' บางส่วน (เช่น CEST) ซึ่งด้วยตนเองจะมีเขตเวลาทางภูมิศาสตร์ 'ที่เฉพาะเจาะจงมากขึ้น (เช่นยุโรป / อัมสเตอร์ดัม)

หากคุณใช้เขตเวลาเหล่านี้และข้อมูล offset / DST สิ่งสำคัญคือการตระหนักถึงสิ่งต่อไปนี้:

ดูเหมือนว่าการกำหนดค่า offset / DST ที่แตกต่างกันทั้งหมด (รวมถึงการกำหนดค่าในอดีต) ของแต่ละเขตเวลาจะรวมอยู่!

ตัวอย่างเช่น Europe / Amsterdam สามารถพบได้หกครั้งในผลลัพธ์ของฟังก์ชันนี้ สองเหตุการณ์ (ชดเชย 1172/4772) สำหรับเวลาอัมสเตอร์ดัมที่ใช้จนถึงปี 1937 สอง (1200/4800) เป็นเวลาที่ใช้ระหว่าง 2480 และ 2483; และสอง (3600/4800) เป็นเวลาที่ใช้ตั้งแต่ปี 1940

ดังนั้นคุณไม่สามารถพึ่งพาข้อมูล offset / DST ที่ส่งคืนโดยฟังก์ชันนี้ว่าถูกต้อง / ใช้งานในขณะนี้!

หากคุณต้องการทราบ offset / DST ปัจจุบันของเขตเวลาที่แน่นอนคุณจะต้องทำสิ่งนี้:

<?php
$now = new DateTime(null, new DateTimeZone('Europe/Amsterdam'));
echo $now->getOffset();
?>

5

หากคุณเกิดขึ้นในการบำรุงรักษาระบบฐานข้อมูลที่ทำงานด้วย DST ที่ใช้งานอยู่ตรวจสอบอย่างรอบคอบว่าพวกเขาจะต้องปิดตัวลงในช่วงการเปลี่ยนแปลงในฤดูใบไม้ร่วง แมนดี้ดีบีเอส (หรือระบบอื่น ๆ เช่นกัน) ไม่ชอบที่จะผ่านจุดเดียวกันในเวลา (ท้องถิ่น) สองครั้งซึ่งเป็นสิ่งที่เกิดขึ้นเมื่อคุณหันหลังนาฬิกาตก SAP แก้ปัญหานี้ด้วยวิธีการแก้ปัญหา (IMHO จริงๆเรียบร้อย) - แทนที่จะหันหลังนาฬิกาพวกเขาเพียงแค่ปล่อยให้นาฬิกาภายในทำงานที่ความเร็วครึ่งปกติเป็นเวลาสองชั่วโมง ...


4

คุณใช้. NET Frameworkหรือไม่ ถ้าเป็นเช่นนั้นฉันขอแนะนำคุณกับประเภทDateTimeOffsetเพิ่มด้วย. NET 3.5

โครงสร้างนี้เก็บทั้ง a DateTimeและ Offset ( TimeSpan) ซึ่งระบุความแตกต่างระหว่างDateTimeOffsetวันที่และเวลาของอินสแตนซ์กับ Coordinated Universal Time (UTC)

  • DateTimeOffset.NowวิธีคงจะกลับDateTimeOffset เช่นประกอบด้วยเวลาปัจจุบัน (ท้องถิ่น) และท้องถิ่นชดเชย (ตามที่กำหนดไว้ในข้อมูลในระดับภูมิภาคของระบบปฏิบัติการ)

  • DateTimeOffset.UtcNowวิธีคงจะกลับ DateTimeOffsetอินสแตนซ์ที่ประกอบด้วยเวลาปัจจุบันใน UTC (เช่นถ้าคุณอยู่ในกรีนวิช)

ชนิดที่เป็นประโยชน์อื่น ๆ ที่มีเขตเวลาและTimeZoneInfoชั้นเรียน


นี่ไม่ใช่วิธีการแก้ไขปัญหาที่นำเสนอ
caradrye

4

สำหรับผู้ที่ดิ้นรนกับสิ่งนี้ใน. NETดูว่าการใช้DateTimeOffsetและ / หรือTimeZoneInfoมีค่าของคุณในขณะที่

หากคุณต้องการใช้เขตเวลาของ IANA / Olsonหรือค้นหาชนิดที่มีอยู่แล้วนั้นไม่เพียงพอสำหรับความต้องการของคุณให้ตรวจสอบNoda Timeซึ่งมีวันที่และเวลา API ที่ชาญฉลาดมากสำหรับ. NET


4

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

ภายในให้บันทึกเวลาในบางสิ่งบางอย่างเช่นพลเรือนเวลาวินาทีจากยุค ยุคไม่สำคัญโดยเฉพาะอย่างยิ่ง (ผมชอบยุค Unix ) แต่มันจะทำให้สิ่งที่ง่ายกว่าทางเลือก แสดงว่าการกระโดดวินาทีไม่ได้เกิดขึ้นถ้าคุณไม่ได้ทำสิ่งที่ต้องการจริงๆ (เช่นการติดตามด้วยดาวเทียม) การแมประหว่างการประทับเวลาและเวลาที่แสดงเป็นเพียงจุดเดียวที่ควรใช้กฎDST กฎมีการเปลี่ยนแปลงบ่อยครั้ง (ในระดับโลกหลายครั้งต่อปีหรือตำหนินักการเมือง) ดังนั้นคุณควรตรวจสอบให้แน่ใจว่าคุณไม่ได้เขียนรหัสการแมปอย่างหนัก ฐานข้อมูล TZของ Olson มีค่ายิ่ง


3
ปัญหาที่นี่คือเวลาพลเรือน (เวลาปฏิทิน aka) ไม่ถูกต้องแสดงช่วงเวลาเดียว หากคุณใช้วิธีวินาทีจากยุคคุณจะบัญชีสำหรับทุกช่วงเวลาที่ถูกข้ามไปหรือย้อนกลับสำหรับการเปลี่ยนการออมในเวลากลางวันหรือไม่? อาจจะไม่. พื้นฐาน Epoch ใช้งานได้กับ UTC หรือการอ้างอิงคงที่แบบทันทีทันเวลาบางส่วนเท่านั้น
Matt Johnson-Pint

@ MattJohnson ดังนั้นส่วน "กฎธุรกิจ" หากกฎพูดว่ามีบางสิ่งเกิดขึ้นในเวลา 2:30 น. ในตอนเช้า (หรือเวลาใดก็ได้) มันจะเกิดขึ้นสองครั้งในหนึ่งวันต่อปีและไม่เคยอยู่ในหนึ่งวันต่อปี นั่นคือสิ่งที่ลูกค้าคาดหวังว่าจะเกิดขึ้นหากพวกเขาไม่ได้ชี้แจงกฎ
user253751

การรักษาเวลาประทับภายในตามเวลาพลเรือนอาจเป็นเรื่องยุ่งยากมาก เก็บไว้เป็นวินาทีตั้งแต่ยุคยังคงมีเล่ห์เหลี่ยมฉันจะบอกว่าอันตรายอย่างจริงจัง ฉันแน่ใจว่ามีคนทำอยู่และอาจเป็นไปได้ที่จะทำงานได้อย่างถูกต้องโดยส่วนใหญ่หากคุณระมัดระวังอย่างยิ่ง แต่ก็ไม่ถือว่าเป็นการปฏิบัติที่ดีที่สุดหรือคำแนะนำทั่วไป
Steve Summit

2

แค่ต้องการชี้ให้เห็นสองสิ่งที่ดูเหมือนไม่ถูกต้องหรืออย่างน้อยก็สับสน:

คงเวลาไว้เสมอตามมาตรฐานรวมที่ไม่ได้รับผลกระทบจากการประหยัดเวลากลางวัน ผู้คนต่างพูดถึง GMT และ UTC แต่ UTC มักจะพูดถึงบ่อยที่สุด

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

รวมการชดเชยเวลาท้องถิ่นตามที่เป็นอยู่ (รวมถึงการชดเชยเวลา) ในการจัดเก็บเวลาประทับ

การประทับเวลาจะแสดงเป็น GMT เสมอดังนั้นจึงไม่มีการชดเชย


1
การชดเชยเวลาในท้องถิ่นจะช่วยให้คุณสามารถสร้าง "กำแพงเวลา" เดิมของเหตุการณ์ หากคุณไม่เก็บฟิลด์เพิ่มเติมนี้ข้อมูลนี้จะหายไป
nogridbag

ใช่ยกเว้นการชดเชย UTC และ GMT เป็นสิ่งที่ตรงกันข้าม ตัวอย่างเช่น UTC-0700 เหมือนกับ GMT + 0700 จริง ๆ แล้วทุกสิ่งที่ดิจิทัลควรใช้ UTC วันนี้
Matt Johnson-Pint

1
@Matt: คุณแน่ใจเกี่ยวกับการปรับค่า UTC และ GMT เป็นค่าผกผันหรือไม่ ฉันจะอ่านได้ที่ไหน
Reto Höhener

จริงๆแล้วฉันคิดว่าฉันไม่ถูกต้องมาก่อน GMT และ UTC ไม่ได้กลับตัวเอง มันมีการใช้งานที่แสดงพวกเขาในสิ่งที่ตรงกันข้ามเช่นฐานข้อมูล IANA / Olson / TZDB ดูที่นี่ อีกพื้นที่ที่คุณเห็นการชดเชยในสิ่งที่ตรงกันข้ามคือฟังก์ชัน getTimezoneOffset () ของ javascript
Matt Johnson-Pint

@ MattJohnson: แฮ็กเหล่านั้นและควรถูกยกเลิก
Alix Axel

2

นี่คือประสบการณ์ของฉัน: -

(ไม่ต้องใช้ห้องสมุดบุคคลที่สาม)

  • บนฝั่งเซิร์ฟเวอร์เก็บเวลาในรูปแบบ UTC เพื่อให้ค่าวันที่ / เวลาทั้งหมดในฐานข้อมูลอยู่ในมาตรฐานเดียวโดยไม่คำนึงถึงสถานที่ตั้งของผู้ใช้เซิร์ฟเวอร์เขตเวลาหรือ DST
  • ในเลเยอร์ UI หรือในอีเมลที่ส่งถึงผู้ใช้คุณต้องแสดงเวลาตามผู้ใช้ สำหรับเรื่องนี้คุณต้องมีการชดเชยเขตเวลาของผู้ใช้เพื่อให้คุณสามารถเพิ่มการชดเชยนี้ให้กับค่า UTC ของฐานข้อมูลของคุณซึ่งจะส่งผลให้เกิดเวลาท้องถิ่นของผู้ใช้ คุณสามารถใช้เขตเวลาชดเชยของผู้ใช้เมื่อพวกเขาลงทะเบียนหรือคุณสามารถตรวจจับพวกเขาโดยอัตโนมัติในเว็บและแพลตฟอร์มมือถือ สำหรับเว็บไซต์ฟังก์ชันเมธอด getTimezoneOffset () ของ JavaScript เป็นมาตรฐานตั้งแต่เวอร์ชัน 1.0 และเข้ากันได้กับเบราว์เซอร์ทั้งหมด (Ref: http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp )

สิ่งนี้จะไม่ทำงานเมื่อคุณพิจารณาการเปลี่ยนแปลงเวลา getTimezoneOffsetส่งคืนออฟเซ็ตสำหรับวันที่และเวลาที่คุณเรียกใช้ ออฟเซ็ตนั้นสามารถเปลี่ยนแปลงได้เมื่อมีการเปลี่ยนเขตเวลาในหรือนอกเวลาออมแสง โปรดดูที่ "โซนเวลา! = ชดเชย" ในวิกิพีเดียแท็กเขตเวลา
Matt Johnson-Pint

1
หากคุณต้องการเก็บการเตือนเช่น "ทำบางอย่างเวลา 10:00" คุณจะไม่สามารถจัดเก็บใน UTC ได้เนื่องจากการเลื่อนเวลา คุณต้องเก็บมันสัมพันธ์กับเวลาท้องถิ่น
อเล็กซ์

2

วิดีโอของ Tom Scott เกี่ยวกับเขตเวลาบน YouTubeในช่อง Computerphile มีคำอธิบายที่ดีและสนุกสนานของหัวข้อ ตัวอย่างรวมถึง:

  • ซามัว (เกาะในมหาสมุทรแปซิฟิก) ขยับเขตเวลาไปข้างหน้า 24 ชั่วโมงเพื่อให้การค้าง่ายขึ้นกับออสเตรเลียและนิวซีแลนด์
  • เวสต์แบงก์ที่ประชากร 2 คนติดตามเขตเวลาต่างกัน
  • การเปลี่ยนแปลงในศตวรรษที่ 18 จากปฏิทินจูเลียนเป็นปฏิทินเกรกอเรียน (ซึ่งเกิดขึ้นในศตวรรษที่ 20 ในรัสเซีย)

1

ที่จริงแล้ว kernel32.dll จะไม่ส่งออก SystemTimeToTzSpecificLocation อย่างไรก็ตามจะส่งออกสองรายการต่อไปนี้: SystemTimeToTzSpecificLocalTime และ TzSpecificLocalTimeToSystemTime ...


1

ไม่เคยพึ่งพาเฉพาะสิ่งก่อสร้างเช่น

 new DateTime(int year, int month, int day, int hour, int minute, TimeZone timezone)

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


1

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

หลายปีที่ผ่านมาระบบปฏิบัติการ Android ใช้ดาวเทียม GPS เพื่อรับการอ้างอิงเวลา UTC แต่ไม่สนใจข้อเท็จจริงที่ว่าดาวเทียม GPS ไม่ได้ใช้ leap-วินาที ไม่มีใครสังเกตจนกว่าจะมีความสับสนในวันส่งท้ายปีเก่าเมื่อผู้ใช้โทรศัพท์ Apple และผู้ใช้โทรศัพท์ Android ทำการนับถอยหลังกันประมาณ 15 วินาที

ฉันคิดว่ามันได้รับการแก้ไขแล้ว แต่คุณไม่มีทางรู้ว่าเมื่อ 'รายละเอียดเล็กน้อย' เหล่านี้จะกลับมาหลอกหลอนคุณ


1
  • ไม่เคยจัดเก็บเวลาท้องถิ่นโดยไม่มีออฟเซ็ต UTC (หรืออ้างอิงถึงเขตเวลา) - ตัวอย่างวิธีไม่รวม FAT32 และstruct tmในC.¹
  • ทำความเข้าใจว่าเขตเวลาคือการรวมกันของ
    • ชุดออฟเซ็ต UTC (เช่น +100 ในฤดูหนาว +0200 ในฤดูร้อน)
    • กฎสำหรับการเปลี่ยนแปลงที่เกิดขึ้น (ซึ่งอาจมีการเปลี่ยนแปลงเมื่อเวลาผ่านไป: ตัวอย่างเช่นในปี 1990 สหภาพยุโรปได้ประสานการเปลี่ยนแปลงอย่างต่อเนื่องในวันอาทิตย์สุดท้ายของเดือนมีนาคมและตุลาคมเวลา 02:00 ตามเวลามาตรฐาน / 03:00 00 DST; ระหว่างรัฐสมาชิก)

implement การนำไปปฏิบัติบางอย่างของการstruct tmจัดเก็บ UTC ตรงข้าม แต่สิ่งนี้ไม่ได้ทำให้เป็นมาตรฐาน


-4

ในการจัดการกับฐานข้อมูล (โดยเฉพาะMySQLแต่สิ่งนี้ใช้ได้กับฐานข้อมูลส่วนใหญ่) ฉันพบว่ามันยากที่จะเก็บ UTC

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

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

หากคุณมีการควบคุมเซิร์ฟเวอร์ 100% และรหัสทั้งหมดอาจเป็นการดีกว่าที่จะเปลี่ยนเขตเวลาของเซิร์ฟเวอร์เป็น UTC


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

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