Yaz saati uygulaması ve saat dilimi için en iyi uygulamalar [kapalı]


2046

Bu soruyu ve cevaplarını, özellikle de fiili değişikliklerle uğraşmak için yaz saati uygulamasıyla ilgili kesin bir kılavuz haline getirmeyi umuyorum.

Ekleyecek bir şeyiniz varsa, lütfen

Birçok sistem doğru zamanı tutmaya bağımlıdır, sorun gün ışığından yararlanma nedeniyle saatteki değişikliklerle ilgilidir - saati ileri veya geri hareket ettirmek.

Örneğin, bir sipariş alma sisteminde siparişin zamanına bağlı olan iş kuralları vardır - saat değişirse, kurallar o kadar açık olmayabilir. Emrin süresi nasıl devam etmeli? Elbette sonsuz sayıda senaryo var - bu sadece açıklayıcı bir senaryodur.

  • Gün ışığından yararlanma sorunuyla nasıl başa çıktınız?
  • Çözümünüzün hangi varsayımlarıdır? (burada bağlam arıyor)

Daha da önemli değilse, önemli olarak:

  • İşe yaramayan ne denediniz?
  • Neden işe yaramadı?

Programlama, işletim sistemi, veri kalıcılığı ve sorunun diğer ilgili yönleri ile ilgilenirim.

Genel cevaplar harika, ancak özellikle tek bir platformda mevcutlarsa ayrıntıları da görmek istiyorum.


2
@abatishchev - GETDATE()SQL'de bu şekilde UTC (olduğu gibi) olacaktır DateTime.Now. Ve sunucu herhangi bir otomatik DST değişikliğinden etkilenmeyecektir.
Oded

4
@Oded: "Sunucuda" eklenip eklenmeyeceğini kabul edebilirim. Ancak yine de bu, yerel saate ihtiyaç duyan başka uygulamaları da etkileyebilir. Bu ve diğer nedenlerle Utc zamanını açıkça istemenin daha iyi olduğunu düşünüyorum.
abatishchev

7
UTC, GMT'ye tercih edilir, çünkü hem daha kesin olarak tanımlanır hem de GMT tanımları bazı işletim sistemlerinde bozulur. İnsanların "GMT" ve "UTC" terimlerini birbirinin yerine kullanılabilir olarak görmeleri yaygındır, ancak bunlar tamamen değildir. Hemen hemen her yazılım / sistem amacı için UTC kullanın. Bkz. Stackoverflow.com/questions/2292334/…
Chris Johnson

7
@JoshStodola - Jon Skeet'in ' cevabı '.
Kenny Evitt

1
@Oded, sunucunun UTC'de olacağını varsayamazsınız, saat diliminin "UTC" olduğu ancak DST uygulanmış olduğu için üretim sunucularını gördüm, bu yüzden yılın yarısından fazlası UTC + 1 idi. Açık ve kullanımı olmak @abatishchev katılıyorum DateTime.UtcNowve GETUTCDATE(), aynı zamanda aslında bu konuda düşündüm diğer devs gösterir
ono2012

Yanıtlar:


940

Yanıtların ve diğer verilerin özeti: (lütfen sizinkini ekleyin)

Yapmak:

  • Zamanında tam bir andan bahsederken, saati yaz saatinden etkilenmeyen birleşik standarda göre sürdürün. (GMT ve UTC bu açıdan eşdeğerdir, ancak UTC terimini kullanmak tercih edilir. UTC'nin Zulu veya Z saati olarak da bilinir .)
  • Bunun yerine, yerel bir zaman değeri kullanarak bir zamana devam etmeyi seçerseniz, zaman damgasının daha sonra açık bir şekilde yorumlanabilmesi için bu belirli zaman için UTC'den yerel zaman ofsetini ekleyin (bu ofset yıl boyunca değişebilir).
  • Bazı durumlarda, hem UTC saatini hem de eşdeğer yerel saati kaydetmeniz gerekebilir . Bu genellikle iki ayrı alanla yapılır, ancak bazı platformlar datetimeoffsether ikisini de tek bir alanda depolayabilen bir türü destekler .
  • Zaman damgalarını sayısal bir değer olarak saklarken, Unix zamanını kullanın - o zamandan bu yana geçen tam saniye sayısıdır 1970-01-01T00:00:00Z(artık saniye hariç). Daha yüksek hassasiyete ihtiyacınız varsa, bunun yerine milisaniye kullanın. Bu değer, herhangi bir saat dilimi ayarlaması yapılmadan her zaman UTC'ye dayanmalıdır.
  • Daha sonra zaman damgasını değiştirmeniz gerekirse, ofsetin kaydedilen orijinal değerden değişip değişmediğini belirlemek için orijinal saat dilimi kimliğini ekleyin.
  • Gelecekteki olayları planlarken, ofsetin değişmesi yaygın olduğu için UTC yerine genellikle yerel saat tercih edilir. Cevap ve blog gönderisine bakın .
  • Doğum günleri ve yıldönümleri gibi tüm tarihleri ​​saklarken UTC'ye veya başka bir saat dilimine dönüştürmeyin.
    • Mümkün olduğunda, günün saatini içermeyen, yalnızca tarih içeren bir veri türünde saklayın.
    • Böyle bir tür mevcut değilse, değeri yorumlarken her zaman günün saatini göz ardı ettiğinizden emin olun. Günün saatinin göz ardı edileceğinden emin değilseniz, o gün daha güvenli bir temsilci olarak 00:00 Gece yarısı yerine 12:00 Öğlen'i seçin.
  • Saat dilimi ofsetlerinin her zaman tamsayı bir saat olmadığını unutmayın (örneğin, Hint Standart Saati UTC + 05: 30 ve Nepal UTC + 05: 45 kullanır).
  • Java kullanıyorsanız, Java 8 ve üstü için java.time kullanın .
  • Kullanılıyorsa .NET , kullanmayı düşünün Noda Zaman .
  • Noda Time olmadan .NET kullanıyorsanız, DateTimeOffsetbunun genellikle daha iyi bir seçim olduğunu düşünün DateTime.
  • Perl kullanıyorsanız, DateTime kullanın .
  • Python kullanıyorsanız, pytz veya dateutil kullanın .
  • JavaScript kullanarak, kullanmak moment.js ile anı-saat dilimi uzantısı.
  • PHP> 5.2 kullanıyorsanız DateTime, ve DateTimeZonesınıfların sağladığı yerel saat dilimleri dönüşümlerini kullanın . Kullanırken dikkatli olun DateTimeZone::listAbbreviations()- cevaba bakınız . PHP'nin Olson verilerini güncel tutmak için , timezonedb PECL paketini periyodik olarak yükleyin ; cevaba bakınız .
  • C ++ kullanıyorsanız, IANA saat dilimi veritabanını doğru şekilde uygulayan bir kitaplık kullandığınızdan emin olun . Bunlar arasında cctz , ICU ve Howard Hinnant'ın "tz" kütüphanesi sayılabilir .
    • Boost'u saat dilimi dönüşümleri için kullanmayın . İken onun API iddiaları standart IANA desteklemek için (aka "zoneinfo") tanımlayıcılar, bu kabaca onları eşler her bölge olmuş olabilir değişikliklerin zengin tarihini dikkate almadan, POSIX tarzı verilere. (Ayrıca, dosya bakımdan düştü.)
  • Rust kullanıyorsanız, chrono kullanın .
  • Çoğu iş kuralı UTC veya GMT yerine sivil saati kullanır. Bu nedenle, uygulama mantığını uygulamadan önce UTC zaman damgalarını yerel bir saat dilimine dönüştürmeyi planlayın.
  • Saat dilimleri ve ofsetlerin sabit olmadığını ve değişebileceğini unutmayın. Örneğin, tarihsel olarak ABD ve İngiltere aynı tarihleri ​​'ileriye doğru' ve 'geri çekilmek' için kullandılar. Ancak, 2007'de ABD saatlerin değiştiği tarihleri ​​değiştirdi. Bu, yılın 48 haftası için Londra saati ile New York zamanı arasındaki farkın 5 saat ve 4 hafta (ilkbaharda 3, sonbaharda 1) 4 saat olduğu anlamına gelir. Birden çok bölge içeren hesaplamalarda bu gibi öğelere dikkat edin.
  • Doğru geri alma için hangi öğelerin (zaman damgası, saat dilimi ofseti ve saat dilimi adı) depolamanız gereken zaman türünü (gerçek olay zamanı, yayın zamanı, göreli zaman, geçmiş zaman, yinelenen zaman) göz önünde bulundurun - bkz. bu cevap .
  • İşletim sisteminizi, veritabanınızı ve uygulama tzdata dosyalarınızı, kendileri ve dünyanın geri kalanı arasında senkronize tutun.
  • Sunucularda, donanım saatlerini ve işletim sistemi saatlerini yerel bir saat dilimi yerine UTC olarak ayarlayın.
  • Ne olursa olsun önceki madde noktasının, sunucu tarafı kod, web siteleri de dahil olmak üzere, gereken asla sunucunun yerel saat dilimi özel bir şey olmasını bekliyoruz. cevaba bakınız .
  • Yapılandırma ayarları veya varsayılanları yerine global olarak değil, uygulama kodunuzda zaman dilimleriyle çalışmayı tercih edin.
  • Tüm sunucularda NTP hizmetlerini kullanın .
  • FAT32 kullanıyorsanız , zaman damgalarının UTC yerine yerel saatte saklandığını unutmayın.
  • Tekrarlanan etkinliklerle uğraşırken (örneğin haftalık TV şovu), zamanın DST ile değiştiğini ve zaman dilimleri arasında farklı olacağını unutmayın.
  • Tarih-saat değerlerini her zaman alt sınır dahil, üst sınır özel ( >=, <) olarak sorgulayın .

Yapma:

  • Gibi bir "zaman dilimi" karıştırmayın, gibi America/New_Yorkbir "zaman dilimi ofseti" gibi -05:00. Bunlar iki farklı şey. Bkz . Saat dilimi etiketi wiki .
  • DateEski web tarayıcılarında tarih ve saat hesaplamaları yapmak için JavaScript nesnesini kullanmayın , çünkü ECMAScript 5.1 ve önceki sürümlerinde yaz saatini yanlış kullanabilen bir tasarım hatası vardır. (Bu, ECMAScript 6 / 2015'te giderilmiştir).
  • Asla müşterinin saatine güvenmeyin. Çok yanlış olabilir.
  • İnsanlara "her yerde UTC'yi kullanmalarını" söyleme. Bu yaygın tavsiye, bu belgede daha önce açıklanan birkaç geçerli senaryodan uzaktır. Bunun yerine, üzerinde çalıştığınız veriler için uygun zaman referansını kullanın. ( Zaman damgası UTC'yi kullanabilir, ancak gelecekteki zaman planlaması ve yalnızca tarih değerleri kullanılmamalıdır.)

Test yapmak:

  • Test yaparken, Batı, Doğu, Kuzey ve Güney yarımkürelerdeki ülkeleri (aslında dünyanın her çeyreğinde, yani 4 bölgede), her ikisi de DST devam ediyor (8 veriyor) ve bunu yapan bir ülke test ettiğinizden emin olun. DST kullanmayın (tüm bölgeleri kapsayacak şekilde 4 tane daha, toplamda 12).
  • DST'nin test geçişini, yani şu anda yaz aylarındayken, kıştan bir zaman değeri seçin.
  • UTC + 12 olan bir saat dilimi gibi DST ile sınır durumlarını test edin, yerel saati UTC + 13 yazın ve hatta kışın UTC + 13 olan yerler yapın
  • Tüm üçüncü taraf kitaplıklarını ve uygulamalarını test edin ve saat dilimi verilerini doğru kullandıklarından emin olun.
  • En azından yarım saatlik zaman dilimlerini test edin.

Referans:

Diğer:

  • DST olan iğrençliği sona erdirmek için temsilcinizi lobi yapın. Her zaman umut edebiliriz ...
  • Dünya Standart Saati için Lobi

31
GMT'yi kullanmak sorunu gerçekten çözmez, yine de uygulamak için doğru deltanın ne olduğunu bulmanız gerekir ve bu tüm karmaşıklığın yattığı yerdir. Delta, farklı bölgelerdeki (farklı gün ışığından yararlanma saati programlarına sahip) kullanıcılar tarafından kullanılan sistemlerde veya geçmiş / gelecekteki verileri gösteren sistemlerde belirlemek karmaşık olabilir.
ckarras

10
Uygulamanın tek yapması gereken geçerli yerel saati görüntülemekse doğrudur. Ancak, örneğin Avustralya'da 2 Nisan 2006'da Kanada'da bir işlemin tarihini / saatini görüntülemesi gereken bir sunucumuz varsa (Kanada'da gün ışığından yararlanma anahtarlama kuralları değişmeden önceki son yıldı) - işletim sistemi çağrınız var mı? DateTime ("2006/04/02 14: 35Z"). ToLocalTime (). WithDaylightSavingRules ("Kanada", 2006)?
ckarras

22
Evet, Windows'ta böyle bir işletim sistemi çağrısı var - SystemTimeToTzSpecificLocation. msdn.microsoft.com/tr-tr/library/ms724949(VS.85).aspx
Michael Madsen

7
@tchrist Belki ısrarcıysan yapabilirsin.
Peter Ajtai

16
Gelecek tarihleri ​​(sadece yarın bile) UTC'ye dönüştürmeyi unutmayın; her zaman bir şeyler kaybedersiniz. Örneğin, bu dönüşümü yapmak için bilinen bir ofset kullandınız, ancak tarih gelecekte olduğundan, bu kuralları belirleyen grubun bu kuralları değiştirme şansı her zaman vardır. Ayrıca, gelecekteki bazı tarihleri ​​UTC'ye dönüştürmek neredeyse imkansızdır, çünkü gün ışığından yararlanma saatleri o yıla kadar bilinmemektedir (bazı ülkeler tarihleri ​​10 yıldan fazla değil, belirlenmiş kurallara dayanarak her yıl belirler).
eselk

319

Yukarıdaki cevaplara neler ekleyebileceğimden emin değilim, ama benden birkaç nokta:

Zaman türleri

Dikkate almanız gereken dört farklı zaman vardır:

  1. Etkinlik zamanı: örneğin, uluslararası bir spor etkinliğinin gerçekleştiği zaman veya taç giyme töreni / ölüm / vb. Bu, izleyiciye değil, olayın saat dilimine bağlıdır.
  2. Televizyon zamanı: Örneğin, belirli bir TV şovu tüm dünyada yerel saatle 21: 00'da yayınlanmaktadır. Web sitenizdeki sonuçları (örneğin American Idol) yayınlamayı düşünürken önemlidir
  3. Göreceli zaman: örneğin: Bu sorunun 21 saat içinde kapanış açık bir ödülü vardır. Bunu görüntülemek kolaydır
  4. Yinelenen zaman: örn: DST değişse bile her Pazartesi saat 9'da bir TV şovu açılır.

Ayrıca Tarihi / alternatif zaman vardır. Bunlar can sıkıcıdır, çünkü standart zamanla eşleşmeyebilirler. Örn: Julian tarihleri, Satürn'ün Ay takvimi, Klingon takvimi ile başlar.

Başlangıç ​​/ bitiş zaman damgalarını UTC'de depolamak işe yarar. 1 için, olayla birlikte depolanan bir olay saat dilimi adı + ofsetine ihtiyacınız vardır. 2 için, her bölge ile birlikte depolanan bir yerel zaman tanımlayıcısına ve her izleyici için depolanan bir yerel saat dilimi adı + ofsetine ihtiyacınız vardır (eğer bir sorun yaşıyorsanız bunu IP'den türetmek mümkündür). 3 saniye boyunca UTC saniyede saklayın ve zaman dilimlerine gerek yok. 4, genel veya yerel bir olay olmasına bağlı olarak 1 veya 2 özel bir durumdur, ancak bu olayı oluşturulmadan önce veya sonra bir zaman dilimi tanımının değişip değişmediğini anlayabilmeniz için oluşturulan bir zaman damgasında saklamanız gerekir . Tarihsel verileri göstermeniz gerekiyorsa bu gereklidir.

Depolama süreleri

  • Her zaman UTC'de depola
  • Ekrandaki yerel saate dönüştür (yerel veriye bakan kullanıcı tarafından tanımlanır)
  • Bir saat dilimini saklarken, ad, zaman damgası ve ofsete ihtiyacınız vardır. Bu, hükümetler bazen zaman dilimlerinin anlamlarını değiştirdiği için (örneğin, ABD hükümeti DST tarihlerini değiştirdi) ve uygulamanızın şeyleri zarif bir şekilde ele alması gerekiyor ... ör .: LOST bölümlerinin DST kurallarından önce ve sonra gösterdiği tam zaman damgası değişti.

Ofsetler ve isimler

Yukarıdakilere örnek olarak şunlar verilebilir:

Futbol dünya kupası finalleri maçı 11 Temmuz 2010 tarihinde 19:00 UTC'de Güney Afrika'da (UTC + 2 - SAST) gerçekleşti.

2010 WCS Final Güney Afrika zaman dilimi tanım değişiklikleri, bile gerçekleştiği Bu bilgilerle, biz tarihsel olarak tam olarak ne zaman belirleyebilir ve onlar veritabanını sorguladığınızda zamanda kendi yerel saat diliminde izleyiciler bunu gösteririz edebilmek.

Sistem zamanı

Ayrıca işletim sisteminizi, veritabanınızı ve uygulama tzdata dosyalarınızı hem birbirinizle hem de dünyanın geri kalanıyla senkronize tutmanız ve yükselttiğinizde kapsamlı bir şekilde test etmeniz gerekir. Bağımlı olduğunuz bir üçüncü taraf uygulamasının bir TZ değişikliğini doğru bir şekilde gerçekleştirmediği duyulmamış.

Donanım saatlerinin UTC olarak ayarlandığından emin olun ve dünyanın her yerinde sunucu çalıştırıyorsanız, işletim sistemlerinin de UTC kullanacak şekilde yapılandırıldığından emin olun. Saatlerce döndürülen apache günlük dosyalarını birden fazla zaman dilimindeki sunuculardan kopyalamanız gerektiğinde bu görünür hale gelir. Bunları dosya adına göre sıralamak yalnızca tüm dosyalar aynı saat dilimiyle adlandırılmışsa çalışır. Ayrıca, bir kutudan diğerine ssh yaptığınızda ve zaman damgalarını karşılaştırmanız gerektiğinde kafanızda tarih matematik yapmak zorunda olmadığınız anlamına gelir.

Ayrıca, tüm kutularda ntpd'yi çalıştırın.

Müşteriler

Bir istemci makineden aldığınız zaman damgasına asla geçerli olarak güvenmeyin. Örneğin, Tarih: HTTP üstbilgileri veya bir javascript Date.getTime()çağrısı. Opak tanımlayıcı olarak kullanıldığında veya aynı istemcide tek bir oturum sırasında tarih matematiği yaparken bunlar iyidir, ancak bu değerleri sunucuda bulunan bir şeyle çapraz referans yapmaya çalışmayın. İstemcileriniz NTP çalıştırmıyor ve BIOS saatleri için çalışan bir pilleri olmayabilir.

önemsiz şeyler

Son olarak, hükümetler bazen çok garip şeyler yapacaklar:

Hollanda'daki standart süre, 1909-05-01'den 1937-06-30'a kadar kanunla UTC'den tam olarak 19 dakika ve 32.13 saniye idi. Bu saat dilimi SS: DD biçimiyle tam olarak temsil edilemez.

Tamam, sanırım işim bitti.


6
Bu cevabın bazı harika noktaları var, özellikle "Tekrar eden zaman: örneğin: DST değişse bile her Pazartesi saat 9'da bir TV şovu" bölümünü belirtmek istedim. zaman dilimleri ile başa çıkmanın zor yönleri. Bununla birlikte, DST bariyerlerini geçen "tekrar eden olayların" ele alınması çok daha zorlaşır.
Jared Hales

45
Ivır zıvır şeyler için +1. İçeriği ilginç tutmak bu görevi daha keyifli hale getirir, bu da üretkenliğin artmasına neden olabilir :)
Chris

4
Bu cevapta çok iyi şeyler var, ama birkaç sorun var. 1) Birçok saat dilimi kısaltması belirsizdir. Buraya bakınız 2) Her zaman UTC'de saklamak istemezsiniz. Çoğu zaman - evet, ama bağlam önemlidir. Terimlerinizle, televizyon zamanı UTC'de saklanmaz. Ayrıca, bazen yasa dışı veya yerel saati saklamama politikasına karşı - bu DateTimeOffset(veya eşdeğeri) gibi şeylerin işe yaradığı yerdir . Aksi takdirde, iyi yazma.
Matt Johnson-Pint

1
Böylece, herkes Joda kütüphanesinin iş için mevcut en iyi araç olduğunu kabul eder. Bununla birlikte, en son saat dilimi bilgilerini güncel tutmak için JODA jar dosyasını bu makaleye göre ( joda.org/joda-time/tz_update.html ) güncellemeye (yeniden oluşturmaya) devam etmeliyiz . IANA web sitesinden ( iana.org/time-zones ) en son saat dilimi verilerini indirmenin ve joda kütüphanesini yeniden oluşturmanın standart bir yolu var mı ? Başka bir deyişle, bu işlemi elle yapmak yerine otomatikleştirmek mümkün müdür?
saravana_pc

2
Hollanda trivia yasal görünüyor. ietf.org/rfc/rfc3339.txt bölüm 5.8. Yarısı birinin bacağımızı çektiğini düşündü.
14'te

89

Bu önemli ve şaşırtıcı derecede zor bir konudur. Gerçek şu ki, kalıcı zaman için tamamen tatmin edici bir standart yoktur. Örneğin, SQL standardı ve ISO formatı (ISO 8601) açıkça yeterli değildir.

Kavramsal açıdan bakıldığında, kişi genellikle iki tür zaman-tarih verisi ile ilgilenir ve bunları ayırt etmek uygundur (yukarıdaki standartlar yoktur): " fiziksel zaman " ve " sivil zaman ".

"Fiziksel" bir zaman anı, sürekli evrensel zaman çizelgesinde fiziğin uğraştığı bir noktadır (elbette göreliliği görmezden gelmek). Bu kavram, örneğin UTC'de yeterince kodlanmış olarak kalıcı olabilir (artık saniyeleri yoksayabilirsiniz).

"Medeni" zaman, medeni normları takip eden bir tarih-saat özelliğidir: burada bir nokta, bir dizi tarih-saati alanı (Y, M, D, H, MM, S, FS) artı bir TZ (saat dilimi belirtimi) ile tam olarak belirtilir (aslında bir "takvim"; ancak tartışmayı Gregoryen takvimi ile sınırladığımızı varsayalım). Bir saat dilimi ve bir takvim (ilke olarak) bir sunumdan diğerine eşleme yapmayı sağlar. Ancak sivil ve fiziksel zaman örnekleri temelde farklı büyüklük türleridir ve kavramsal olarak ayrı tutulmalı ve farklı şekilde ele alınmalıdır (bir analoji: bayt dizileri ve karakter dizileri).

Sorun kafa karıştırıcı çünkü bu tür olaylardan birbirinin yerine geçiyor ve sivil zamanlar politik değişikliklere maruz kalıyor. Sorun (ve bu kavramları ayırt etme ihtiyacı) gelecekteki olaylar için daha belirgin hale gelmektedir. Örnek ( buradaki tartışmamdan alınmıştır .

John takviminde datetime 2019-Jul-27, 10:30:00, TZ = Chile/Santiago(GMT-4'ü dengeleyen, dolayısıyla UTC'ye karşılık gelen 2019-Jul-27 14:30:00) bir olay için hatırlatma kaydeder . Ancak gelecekte bir gün, ülke TZ ofsetini GMT-5 olarak değiştirmeye karar veriyor.

Şimdi, gün geldiğinde ... bu hatırlatıcı

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

veya

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

John'un "Lütfen beni ara" dediğinde kavramsal olarak ne anlama geldiğini bilmediği sürece doğru bir cevap yoktur 2019-Jul-27, 10:30:00 TZ=Chile/Santiago.

"Medeni tarih-saat" ("benim şehrimdeki saatler 10:30 dediği zaman) mı demek istiyordu? Bu durumda, A) doğru cevaptır.

Yoksa "bir sonraki güneş tutulması gerçekleştiğinde", "evrenimizin sürekli zaman çizgisinde bir nokta olan" fiziksel bir anlık an "anlamına mı geliyordu. Bu durumda, cevap B) doğrudur.

Birkaç Tarih / Saat API'sı bu ayrımı doğru yapar: aralarında , bir sonraki (üçüncü!) Java DateTime API'sının (JSR 310) temeli olan Jodatime .


1
API'larda ele alınmadığını gördüğüm bir başka nokta, zaman ve saat dilimi verildiğinde bile, örneğin "13: 00: 00EDT" için en az iki mantıklı anlamın olmasıdır. Yerel saat 13.00'te olduğu bilinen ve Doğu Yaz Saati olduğuna inanılan bir şeye veya Doğu saatinin 13: 00'a çarptığı sanıldığı bilinen bir şeye atıfta bulunabilir. Doğu Yaz Saati'ni gözlemleyen bir yerde meydana gelmiştir. Saat dilimi bilgilerinin yanlış olabileceği birçok zaman damgası varsa (örn. Dijital kamera dosyaları) ...
supercat

1
... doğru bir yerel saati mi yoksa küresel saati mi yansıttığını bilmek, bunların nasıl düzeltileceğini belirlemede önemli olabilir.
supercat

3
Açıkçası John A) istiyor çünkü insanlar şu anda DST veya saat dilimi ne olursa olsun 8: 30'da işe gidiyor. Eğer DST'ye girerse, 8: 30'da işe giderler, DST'den çıktıklarında 8: 30'da işe giderler. Ülke başka bir saat dilimine geçmeye karar verirse, her gün 8:30 'da işe giderler
Gianluca Ghettini

59

Endişelerin net bir mimari ayrımı yapın - hangi katmanın kullanıcılarla tam olarak etkileşime girdiğini bilmek ve kurallı sunum için / tarihini (UTC) değiştirmek zorundadır. UTC dışı tarih-saat sunumdur (kullanıcıların yerel saat dilimini izler), UTC saati modeldir (arka uç ve orta katmanlar için benzersiz kalır).

Ayrıca, gerçek kitlenizin ne olduğuna, nelere hizmet etmek zorunda olmadığınız ve nerede çizgi çizdiğinize karar verin . Gerçekten önemli müşterileriniz olmadığı sürece egzotik takvimlere dokunmayın ve ardından yalnızca bu bölge için ayrı kullanıcılara yönelik sunucuları düşünün.

Kullanıcının konumunu alıp koruyabiliyorsanız, sistematik tarih-saat dönüşümü için konumu kullanın (.NET kültürü veya SQL tablosu diyelim), ancak tarih-kullanıcılarınız için tarih-saat kritik ise son kullanıcının geçersiz kılmaları seçmesi için bir yol sağlayın.

İlgili tarihsel denetim yükümlülükleri varsa (AZ'de Jo'nun Eylül ayında 2 yıl önce bir faturayı ne zaman ödediğini söylemek gibi) kayıt için hem UTC hem de yerel saati saklayın (dönüşüm tablolarınız zaman içinde değişecektir).

Toplu dosya, web hizmetleri vb. Gibi gelen veriler için zaman referanslı saat dilimini tanımlayın. East Coast şirketinin CA'da veri merkezi olduğunu varsayalım. Bunlardan birini veya diğerini varsaymak yerine standart olarak ne kullandıklarını sormanız ve bilmeniz gerekir.

Tarih-saatin metinsel temsiline gömülü saat dilimi ofsetlerine güvenmeyin ve bunları ayrıştırıp takip etmeyi kabul etmeyin. Bunun yerine daima zaman dilimi ve / veya referans bölgesinin açıkça tanımlanmasını talep edin . PST ofseti ile kolayca zaman alabilirsiniz, ancak zaman aslında EST'dir, çünkü bu müşterinin referans zamanıdır ve kayıtlar sadece PST'deki bir sunucuda dışa aktarılmıştır.


40

Sen Olson hakkında bilmeniz gereken tz veritabanında edinilebilir, ftp://elsie.nci.nih.gov/pub http://iana.org/time-zones/ . Dünyanın farklı ülkelerinde kış ve yaz (standart ve gün ışığından yararlanma) saatleri arasında ne zaman (ve olup olmadığı) sık sık son dakika değişiklikleriyle başa çıkmak için yılda birkaç kez güncellenir. 2009'da son sürüm 2009'du; 2010 yılında, 2010n oldu; 2011 yılında 2011n idi; Mayıs 2012'nin sonunda, sürüm 2012c idi. İki ayrı arşivde (tzcode20xxy.tar.gz ve tzdata20xxy.tar.gz) verileri ve gerçek zaman dilimi verilerinin kendisini yönetmek için bir kod kümesi bulunduğunu unutmayın. Hem kod hem de veriler kamu malıdır.

Bu Amerika / Los_Angeles gibi zaman dilimi adlarının (ve ABD / Pasifik gibi eşanlamlıların) kaynağıdır.

Farklı bölgeleri takip etmeniz gerekiyorsa, Olson veritabanına ihtiyacınız var. Diğerlerinin de önerdiği gibi, verileri sabit bir biçimde - UTC normalde seçilen olan - depolamak ve verilerin oluşturulduğu saat diliminin bir kaydını saklamak istersiniz. Ofset'i UTC'den saat ve saat dilimi adı arasında ayırt etmek isteyebilirsiniz; daha sonra fark yaratabilir. Ayrıca, şu anda 2010-03-28T23: 47: 00-07: 00 (ABD / Pasifik) olduğunu bilmek, muhtemelen PST'de belirtilen 2010-11-15T12: 30 değerini yorumlamanıza yardımcı olabilir veya etmeyebilir. (Pasifik Standart Saati) yerine PDT (Pasifik Yaz Saati Uygulaması).

Standart C kütüphanesi arayüzleri bu tür şeyler için çok yararlı değildir.


Olson verileri, kısmen AD Olson yakında emekliye ayrılacağı için ve kısmen de telif hakkı ihlali nedeniyle sahiplerine karşı (artık reddedilmiş) bir dava açtığı için taşındı. Saat dilimi veritabanı artık İnternet Atanmış Sayılar Kurumu IANA'nın himayesinde yönetiliyor ve ön sayfada 'Saat Dilimi Veritabanı'na bir bağlantı var . Tartışma posta listesi şu anda tz@iana.org; duyuru listesi tz-announce@iana.org.


12
Olson veritabanı, DST'yi işlemek için özellikle kullanışlı hale getiren geçmiş veriler de içerir . Örneğin, ABD'de 31 Mart 2000'e karşılık gelen bir UTC değerinin DST'de olmadığını, ancak ABD'de 31 Mart 2008'e karşılık gelen bir UTC değerinin olduğunu bilir.
Josh Kelley

3
Unicode Konsorsiyumu Olson tome bölge kimlikleri ve Windows saat dilimi kimlikleri arasında bir eşleme sağlar: unicode.org/repos/cldr-tmp/trunk/diff/supplemental/…
Josh Kelley

Unicode Konsorsiyumu sayfası için güncellenmiş bağlantı: unicode.org/repos/cldr-tmp/trunk/diff/supplemental/…
Span

Olson dosyalarını ayrıştırma hakkında nerede bilgi bulunabilir? Bunu bir db tablosuna derlemek istiyorum, ancak dosyaları nasıl okumam gerektiğini
anlayamıyorum

@gidireich: ana bilgiler verilerle bulunur ve anlaşılması kolay değildir. Bunun için ana belgelerzic.8 kılavuz sayfasında (veya zic.8.txt) bulunmaktadır. Bu bilgiyi almak için tzcode2011i.tar.gzdosya yerine veya dosyaya ihtiyacınız olacaktır tzdata2011i.tar.gz.
Jonathan Leffler

26

Genel olarak, yerel zaman ofsetini (DST ofseti dahil) depolanan zaman damgalarına dahil edin: Daha sonra zaman damgasını orijinal saat diliminde (ve DST ayarında) görüntülemek istiyorsanız, yalnızca UTC yeterli değildir.

Uzaklığın her zaman tamsayı bir saat olmadığını unutmayın (örn. Hint Standart Saati UTC + 05: 30).

Örneğin, uygun biçimler bir demet (unix süresi, dakika cinsinden ofset) veya ISO 8601'dir .


5
Ekran için ofset mükemmel. Değişiklik yapmak istiyorsanız, ofset hala yeterli değildir. Saat dilimini de bilmelisiniz çünkü yeni değer farklı bir ofset gerektirebilir.
Matt Johnson-Pint

23

"Bilgisayar zamanı" ve "insan zamanı" sınırlarını aşmak bir kabustur. Bunlardan en önemlisi, zaman dilimlerini ve gün ışığından yararlanma saatlerini düzenleyen kurallar için bir tür standart olmamasıdır. Ülkeler saat dilimlerini ve DST kurallarını istedikleri zaman değiştirmekte özgürdürler.

İsrail, Brezilya gibi bazı ülkeler, her yıl gün ışığından yararlanma sürelerine ne zaman sahip olacağına karar verir, bu nedenle DST'nin ne zaman geçerli olacağını bilmek imkansızdır. Diğerleri, DST'nin ne zaman yürürlükte olduğuna ilişkin sabit (ish) kurallara sahiptir. Diğer ülkeler DST'yi hiç kullanmazlar.

Zaman dilimleri GMT'den tam saatlik farklar olmak zorunda değildir. Nepal +5.45'tir. Hatta +13 olan zaman dilimleri bile var. Bu şu demek oluyor:

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

hepsi aynı zamanda, henüz 3 farklı gün!

Zaman dilimlerinin kısaltmaları ve DST'deyken nasıl değiştikleri konusunda net bir standart da yoktur, böylece böyle şeylerle sonuçlanırsınız:

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

En iyi tavsiye, mümkün olduğunca yerel saatlerden uzak durmak ve UTC'ye bağlı kalmaktır. Yalnızca mümkün olan en son anda yerel saatlere dönüştürün.

Test yaparken, Batı ve Doğu yarımkürelerdeki ülkeleri hem DST devam ediyor, hem de DST kullanmayan bir ülke (toplam 6) test ettiğinizden emin olun.


İsrail ile ilgili olarak - bu yarı doğrudur. DST değişikliğinin zamanı Julian takviminde belirli bir tarih olmamasına rağmen - İbranice takvimine dayanan bir kural var (2014'te bir değişiklik oldu). Her neyse, genel fikir doğrudur - bu şeyler arada bir değişebilir ve değişebilir
Yaron

1
Ayrıca, AST = Atlantik Standart Saati. 'En iyi tavsiye' gelince, bir başlangıç ​​noktası olarak iyidir, ancak bu sayfanın geri kalanını okumalı ve biraz dua etmelisiniz ve bir süre doğru alabilirsiniz.
DavidWalley

20

PHP için:

PHP> 5.2'deki DateTimeZone sınıfı zaten diğerlerinin bahsettiği Olson DB'ye dayanmaktadır, bu nedenle DB'de değil, PHP'de saat dilimi dönüşümleri yapıyorsanız, Olson dosyaları ile çalışmaktan muaftırsınız.

Bununla birlikte, PHP Olson DB kadar sık ​​güncellenmez, bu yüzden sadece PHP'nin saat dilimi dönüşümlerini kullanmak sizi eski DST bilgileriyle bırakabilir ve verilerinizin doğruluğunu etkileyebilir. Bunun sık sık gerçekleşmesi beklenmese de, olabilir ve olacak dünya çapında kullanıcıların büyük tabanına varsa olur.

Yukarıdaki sorunla başa çıkmak için timezonedb pecl paketini kullanın . İşlevi PHP'nin saat dilimi verilerini güncellemektir. Bu paketi güncellenen sıklıkta yükleyin. (Bu pakette yapılan güncellemelerin Olson güncellemelerini tam olarak takip edip etmediğinden emin değilim, ancak en azından Olson güncellemelerinin sıklığına çok yakın bir sıklıkta güncellenmiş gibi görünüyor.)


18

Tasarımınız bunu karşılayabilirse, yerel saat dönüşümünü hep birlikte önleyin!

Bazılarının çılgınca gelebileceğini biliyorum ama UX'i düşünün: kullanıcılar bakışta mutlak tarihlerden (2010.09.17, Cuma Eylül 17) daha yakın, göreceli tarihleri ​​(bugün, dün, gelecek Pazartesi) daha hızlı işliyorlar. Ve daha fazla düşündüğünüzde, zaman dilimlerinin (ve DST) doğruluğu, tarih ne kadar yakın olursa daha önemlidir now(), bu nedenle tarihleri ​​/ tarihleri ​​+/- 1 veya 2 hafta boyunca göreceli bir biçimde ifade edebiliyorsanız, tarihler UTC olabilir ve kullanıcıların% 95'i için çok önemli değildir.

Bu şekilde tüm tarihleri ​​UTC'de saklayabilir ve göreli karşılaştırmaları UTC'de yapabilir ve kullanıcının UTC tarihlerini Göreceli Tarih Eşiğinizin dışında gösterebilirsiniz.

Bu, kullanıcı girişi için de geçerlidir (ancak genellikle daha sınırlı bir şekilde). Yalnızca {Dün, Bugün, Yarın, Gelecek Pazartesi, Gelecek Perşembe} olan bir açılır menüden seçim yapmak kullanıcı için bir tarih seçiciden çok daha basit ve kolaydır. Tarih seçiciler, form doldurmanın en acı verici bileşenlerinden bazılarıdır. Tabii ki bu tüm durumlar için işe yaramayacak, ancak çok güçlü hale getirmenin sadece akıllı bir tasarım gerektirdiğini görebilirsiniz.


16

Bunu denememiş olsam da, zorlayıcı bulacağım saat dilimi ayarlamalarına bir yaklaşım şöyle olurdu:

  1. Her şeyi UTC'de saklayın.

  2. TZOffsetsÜç sütunlu bir tablo oluşturun : RegionClassId, StartDateTime ve OffsetMinutes (int, dakika olarak).

Tabloda, tarihleri ve saatleri listesini saklamak ne kadar yerel saati değiştirilmiş ve. Tablodaki bölge sayısı ve tarih sayısı, dünyanın hangi tarih ve alan aralığını desteklemeniz gerektiğine bağlı olacaktır. Tarihin geleceği bir miktar pratik sınırlama içermesine rağmen, bunu "tarihsel" tarih gibi düşünün.

Herhangi bir UTC saatinin yerel saatini hesaplamanız gerektiğinde, bunu yapmanız yeterlidir:

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

Bu tabloyu uygulamanızda önbelleğe almak ve veritabanına isabet etmek yerine sorguları yapmak için LINQ veya benzeri araçlar kullanmak isteyebilirsiniz.

Bu veriler kamu malı tz veritabanından damıtılabilir .

Bu yaklaşımın avantajları ve dipnotları:

  1. Kod haline getirilmiş kural yoktur, yeni bölgeler veya tarih aralıkları için ofsetleri kolayca ayarlayabilirsiniz.
  2. Her tarih veya bölgeyi desteklemenize gerek yoktur, gerektiğinde ekleyebilirsiniz.
  3. Bölgeler doğrudan jeopolitik sınırlara karşılık gelmek zorunda değildir ve satırların tekrarlanmasını önlemek için (örneğin, ABD'deki çoğu eyalet DST'yi aynı şekilde işler), başka bir tabloda daha geleneksel listelere bağlanan geniş RegionClass girişlerine sahip olabilirsiniz. eyaletler, ülkeler vb.
  4. ABD gibi DST'nin başlangıç ​​ve bitiş tarihinin son birkaç yılda değiştiği durumlar için, bununla başa çıkmak oldukça kolaydır.
  5. StartDateTime alanı da bir zaman depolayabildiğinden, 2:00 AM standart değiştirme süresi kolayca işlenir.
  6. Dünyanın her yerinde 1 saatlik DST kullanılmıyor. Bu, bu durumları kolayca ele alır.
  7. Veri tablosu çapraz platformdur ve neredeyse tüm veritabanı platformlarını veya programlama dillerini kullanan geliştiriciler tarafından kullanılabilen ayrı bir açık kaynaklı proje olabilir.
  8. Bu, zaman dilimleri ile ilgisi olmayan ofsetler için kullanılabilir. Örneğin, zaman zaman Dünya'nın dönüşünü ayarlamak için meydana gelen 1 saniyelik düzenlemeler, Gregoryen takvimi ve içindeki tarihsel düzenlemeler vb.
  9. Bu bir veritabanı tablosunda olduğundan, standart rapor sorguları vb., İş mantığı kodu üzerinden bir yolculuk yapmadan verilerden yararlanabilir.
  10. Bu, zaman dilimi ofsetlerini de isterseniz yönetir ve hatta bir bölgenin başka bir saat dilimine atandığı özel tarihsel durumları da hesaba katabilir. Tek ihtiyacınız olan, her bölgeye minimum başlangıç ​​tarihiyle bir saat dilimi sapması atayan bir başlangıç ​​tarihidir. Bu, her saat dilimi için en az bir bölge oluşturmayı gerektirir, ancak şu gibi ilginç sorular sormanızı sağlar: "Yuma, Arizona ve Seattle, Washington arasındaki yerel saatte 2 Şubat 1989 saat 05:00 de fark nedir?" (Sadece bir SUM () öğesini diğerinden çıkarın).

Şimdi, bu yaklaşımın tek dezavantajı ya da başka dönüşümleri olmasıdır gelen saatine Negatif bir olan herhangi DST değişikliği beri yerel saat GMT, mükemmel olmayan tekrarlar verilen bir yerel saati. Bununla başa çıkmanın kolay bir yolu yok, korkarım, bu da yerel zamanları saklamanın ilk nedenlerinden biri kötü haber.


8
Veritabanı fikriniz zaten Olson Veritabanı olarak uygulandı. Yaz saati uygulaması, gün ışığına özel saat dilimini belirten bir çakışma oluştururken, sorunun çözülmesine yardımcı olabilir. 2:15 EST ve 2:15 EDT farklı zamanlardır. Ofseti belirten diğer yazılarda belirtildiği gibi, belirsizliği de giderir.
BillThor

5
Kendi veritabanınızı tutmanın en büyük problemi güncel tutmaktır. Olson ve Windows sizin için korunur. Tablolar güncel olmadığı için kötü DST geçişleri olan birden fazla vaka yaşadım. Onları tamamen sökmek ve bir çerçeve veya işletim sistemi düzeyinde veritabanına güvenmek çok daha güvenilirdir.
Matt Johnson-Pint

4
Kendi veritabanınızı yaratmayın : her zaman sistemin API'sine güvenin!
Alex

15

Geçenlerde bir Ajax post-back benim sunucu tarafı koduna geri gelen datetime sunulan datetime farklıydı bir web uygulamasında bir sorun vardı.

Büyük olasılıkla, istemciye dize olarak geri gönderme tarihini oluşturan JavaScript kodumla ilgiliydi, çünkü JavaScript saat dilimi ve gün ışığından yararlanma saatini ayarlıyordu ve bazı tarayıcılarda gün ışığından yararlanma saatinin ne zaman uygulanacağına ilişkin hesaplama diğerlerinden farklı görünüyordu.

Sonunda, istemcideki tarih ve saat hesaplamalarını tamamen kaldırmayı seçtim ve tutarlı dönüşümlere izin vermek için sunucuda tarih saatine çevrilen bir tam sayı anahtarında sunucuma geri gönderdim.

Bundan öğrendiklerim: KESİNLİKLE yapmak zorunda olmadığınız sürece web uygulamalarında JavaScript tarih ve saat hesaplamaları kullanmayın.


Javascript, sunucu makinesinde değil, istemci makinede çalışır. Javascript'in temel datetime değeri, sunucunun datetime değil, istemcinin datetime değeridir.
BalusC

Merhaba BalusC. Bunu anlıyorum (orijinal yazımdan: "tarihi oluşturan istemcideki javacode betiği ..."). Benim sorunum, bazı istemci makinenin DST'yi bir şekilde, bazılarının da başka bir şekilde işlemesi oldu. Bu nedenle, tarayıcı garipliğini önlemek için tüm bu işleme sunucu tarafını taşıdım
Joon

@ Joon — javascript uygulamalarında tespit edemeyeceğiniz veya izin veremeyeceğiniz hatalar var. Bu yüzden evet, önemli olan şeyler için asla istemci tarafı ECMAScript tarih hesaplamaları kullanmayın (aksi halde oldukça iyi bir iş yapabilirsiniz).
RobG

14

Buna iki tip sistemde çarptım: “vardiya planlama sistemleri (örneğin fabrika işçileri)” ve “gaza bağlı yönetim sistemleri)…

23 ve 25 saatlik uzun günler başa çıkmak için bir acıdır, 7 saat veya 9 saat süren 8 saat vardiyaları da. Sorun, her müşterinin veya hatta müşterinin bir bölümünün, bu özel durumlarda yaptıklarına ilişkin oluşturdukları farklı kurallara sahip olduklarını (genellikle belgelemeden) görmenizdir.

Bazı sorular, "hazır" yazılımınız için ödeme yaptıktan sonraya kadar müşterinin sorulmaması en iyisidir. Yazılım satın alırken bu tür bir konuyu düşünen bir müşteri bulmak çok nadirdir.

Her durumda UTC'de zaman kaydetmeniz ve tarihi / saati saklamadan önce yerel saate / zaman dönüştürmeniz gerektiğini düşünüyorum. Bununla birlikte, belirli bir zamanın hangisinde olduğunu bilmek bile Yaz Saati ve zaman dilimleri ile zor olabilir.


6
Kız arkadaşım, hemşire, gece çalışıyor ve DST geçişi sırasında saat dilimini yazmaları gerekiyor. Örneğin, 2AM CST vs 2AM CDT
Joe Phillips

1
Evet, bu yaygındır: (sivil) bir günlük ortalama hesapladığınızda, 23, 24 veya 25 saatlik günlerle başa çıkmanız gerekir. Sonuç olarak, hesaplamak 1 gün eklemek zaman 24 saat eklemek değildir ! İkincisi, kendi saat dilimi kodunuzu oluşturmaya çalışmayın; yalnızca sistem API'sini kullanın. Güncel saat dilimi veritabanını almak için her bir dağıtılmış sistemi güncellemeyi unutmayın .
Alex

12

Web için kurallar o kadar karmaşık değil ...

  • Sunucu tarafı, UTC kullanın
  • İstemci tarafında, Olson kullanın
    • Sebep: UTC ofsetleri gün ışığından tasarruf için güvenli değildir (ör. New York yılın EST (UTC - 5 Saat) kısmı, yılın geri kalan kısmı EDT (UTC - 4 Saat)).
    • İstemci tarafı saat dilimi belirleme için iki seçeneğiniz vardır:

Geri kalanı, sunucu tarafı tarih saat kitaplıklarınızı kullanarak yalnızca UTC / yerel dönüşümdür. Gitmek güzel ...


2
Bu bir başlangıç ​​noktası olarak iyi bir tavsiye, ama tamamen uygulamaya bağlıdır. Bu, arkadaş canlısı bir web sitesi için iyi olabilir, ancak başvurunuzda birisinin dava edebileceği herhangi bir yasal / yargı / mali yönü varsa (birkaç tane üzerinde çalıştım), o zaman bu bir aşırı basitleştirmedir çünkü ' time "olarak adlandırılır.
DavidWalley

12

Web siteleri ve diğer arka uç hizmetleri de dahil olmak üzere bir sunucuda çalışan uygulamalar söz konusu olduğunda , sunucunun saat dilimi ayarı uygulama tarafından yok sayılmalıdır.

Genel tavsiye, sunucunun saat dilimini UTC olarak ayarlamaktır. Bu gerçekten iyi bir uygulama, ancak diğer en iyi uygulamaları takip etmeyen uygulamalar için yara bandı olarak var. Örneğin, bir hizmet UTC tabanlı zaman damgaları yerine yerel zaman damgalarına sahip günlük dosyalarına yazıyor olabilir, böylece yaz saati geri dönüş geçişi sırasında belirsizlikler yaratır. Sunucunun saat dilimini UTC olarak ayarlamak bu uygulamayı düzeltir . Ancak asıl düzeltme, uygulamanın UTC ile başlamak için oturum açması olacaktır.

Web siteleri de dahil olmak üzere Sunucu tarafı kodu, gereken asla sunucunun yerel saat dilimi özel bir şey olmasını bekliyoruz.

Bazı dillerde, yerel saat dilimi uygulama koduna kolayca girebilir. Örneğin, DateTime.ToUniversalTime.NET yöntem dönüştürecektir gelen UTC yerel saat diliminde ve DateTime.Nowmülkiyet yerel saat dilimindeki saati döndürür. AyrıcaDate JavaScript'teki yapıcı bilgisayarın yerel saat dilimini kullanır. Bunun gibi başka örnekler de var. Bilgisayarın yerel saat dilimi ayarını kullanan herhangi bir koddan kaçınarak savunma programlaması yapmak önemlidir.

Masaüstü uygulamaları, mobil uygulamalar ve istemci tarafı JavaScript gibi istemci tarafı kodu için yerel saat dilimini kullanarak ayırın.


11

Sunucularınızı UTC'ye ayarlı tutun ve hepsinin ntp veya eşdeğeri için yapılandırıldığından emin olun.

UTC, gün ışığından yararlanma saati sorunlarını önler ve senkronizasyon dışı sunucular, teşhis edilmesi zaman alan öngörülemeyen sonuçlara neden olabilir.


9

FAT32 dosya sisteminde saklanan zaman damgalarıyla uğraşırken dikkatli olun - yerel zaman koordinatlarında (DST dahil - her zaman devam eder ) msdn makalesine bakın ). Bunun üzerine yandım.


Harika bir nokta. NTFS'de bu sorun yok, ancak bazı insanlar hala özellikle USB anahtarlarında FAT32 kullanıyor.
Matt Johnson-Pint

7

Başka bir şey, sunucuların güncel gün ışığından yararlanma düzeltme eki uygulandığından emin olun.

Geçen sene, UTC tabanlı bir sistem kullanıyor olsak da, Kuzey Amerikalı kullanıcılar için üç haftalık bir süre boyunca zamanlarımızın sürekli olarak bir saat geçtiği bir durum vardı.

Sonunda sunucu olduğu ortaya çıktı. Sadece güncel bir düzeltme ekinin uygulanması gerekiyordu ( Windows Server 2003 ).


6

PHP DateTimeZone::listAbbreviations()çıktısı

Bu PHP yöntemi, kendi başına daha spesifik 'coğrafi' zaman dilimleri (Avrupa / Amsterdam gibi) içeren bazı 'büyük' ​​zaman dilimlerini (CEST gibi) içeren ilişkilendirilebilir bir dizi döndürür.

Bu zaman dilimlerini ve ofset / DST bilgilerini kullanıyorsanız, aşağıdakileri gerçekleştirmek son derece önemlidir:

Her bir zaman diliminin tüm farklı ofset / DST konfigürasyonları (geçmiş konfigürasyonlar dahil) dahil gibi görünüyor !

Örneğin, Avrupa / Amsterdam bu fonksiyonun çıktısında altı kez bulunabilir. 1937'ye kadar kullanılan Amsterdam zamanı için iki tekrarlama (ofset 1172/4772); ikisi (1200/4800), 1937 ve 1940 arasında kullanılan zamandır; ve iki tanesi (3600/4800) 1940'tan beri kullanılmaktadır.

Bu nedenle, bu işlev tarafından döndürülen ofset / DST bilgilerine şu anda doğru / kullanımda olduğu için güvenemezsiniz !

Belirli bir saat diliminin geçerli ofsetini / DST'sini bilmek istiyorsanız, böyle bir şey yapmanız gerekir:

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

5

DST etkinken çalışan veritabanı sistemlerini koruyorsanız, sonbaharda geçiş sırasında kapatılması gerekip gerekmediğini dikkatlice kontrol edin. Mandy DBS (ya da diğer sistemler) aynı noktayı (yerel) zamanda iki kez geçirmekten hoşlanmaz, bu da sonbaharda saati geri çevirdiğinizde tam olarak ne olur. SAP bunu (IMHO gerçekten temiz) bir çözümle çözdü - saati geri çevirmek yerine, dahili saatin iki saat boyunca normal hızın yarısında çalışmasına izin verdiler ...


4

.NET çerçevesini mi kullanıyorsunuz ? Öyleyse, size .NET 3.5 ile eklenen DateTimeOffset türünü tanıtayım .

Bu yapı , örneğin tarihi ve saati ile Eşgüdümlü Evrensel Saat (UTC) arasındaki farkı belirten a DateTimeve bir Uzaklık ( ) içerir.TimeSpanDateTimeOffset

  • DateTimeOffset.NowStatik yöntemi dönecektir DateTimeOffset akım (yerel) zaman oluşan örneğini ve (işletim sisteminin bölgesel bilgi belirtildiği gibi) ofset yerel.

  • DateTimeOffset.UtcNowStatik yöntemi dönecektir DateTimeOffset(eğer Greenwich sanki) UTC'de şimdiki zaman oluşan örneğini.

Diğer yararlı türler TimeZone ve TimeZoneInfo sınıflarıdır.


Bu, sunulan soruna bir çözüm değildir.
caradrye

4

Bu .NET ile mücadele edenler için , DateTimeOffsetve / veya TimeZoneInfosüre değer olup olmadığını bakın .

IANA / Olson saat dilimlerini kullanmak veya yerleşik türlerin ihtiyaçlarınız için yetersiz olduğunu bulmak istiyorsanız, .NET için çok daha akıllı bir tarih ve saat API'si sunan Noda Time'a göz atın .


4

İş kuralları her zaman sivil zaman üzerinde çalışmalıdır (aksi belirtilmedikçe). Sivil zamanın bir karmaşa olduğunu unutmayın, ancak insanların kullandığı şey budur, bu yüzden önemlidir.

Dahili olarak, zaman damgalarını dönemden sivil zaman-saniye gibi bir şeyde tutun. Dönem önemli değil özellikle (ı tercih yapar Unix çağı ) ama alternatifinden daha kolay yapmak şeyler yapar. Bu davran sıçrama-saniye olduğu bir şey yapıyoruz sürece yoktur gerçekten onları (örneğin uydu izleme) ihtiyacı vardır. Zaman damgaları ve görüntülenen zaman arasındaki eşleme, DST kurallarının uygulanması gereken tek noktadır ; kurallar sık ​​sık değişir (küresel düzeyde, yılda birkaç kez; politikacıları suçlayın), bu yüzden eşlemeyi zor kodlamadığınızdan emin olmalısınız. Olson'ın TZ veritabanı paha biçilmezdir.


3
Buradaki sorun, sivil zamanın (takvim zamanı olarak da bilinir) zamanında tek bir anı doğru şekilde temsil etmemesidir. Dönemden saniye yaklaşımı yaparsanız, atlanan her anı gerçekten mi yoksa gün ışığından yararlanma geçişlerini geri mi alacaksınız? Muhtemelen değil. Epoch temeli yalnızca UTC veya başka bir sabit, anlık zamanlı referansa karşı çalışır.
Matt Johnson-Pint

@MattJohnson Bundan dolayı "iş kuralları" bölümü. Kurallar sabah saat 2: 30'da (ya da hangi saatte) bir şey olduğunu söylüyorsa, yılda bir gün iki kez olur ve asla yılda bir gün olmaz. Kuralı açıklığa kavuşturmazsa müşterinin olmasını beklediği de budur .
user253751

İç zaman damgalarını sivil zamanda tutmak çok zor olabilir. Hala bir çığır açıcı olduğu için saniyeler içinde tutmak, düpedüz tehlikeli diyebilirim. Eminim bunu yapan insanlar vardır ve süper dikkatli olursanız çoğu zaman düzgün çalışmasını sağlamak mümkün olabilir, ancak en iyi uygulama veya genel bir tavsiye olarak kabul edilemez.
Steve Summit

2

Sadece yanlış veya en azından kafa karıştırıcı görünen iki şeye işaret etmek istedim:

Yaz saati uygulamasından etkilenmeyen birleşik bir standarda göre her zaman zaman ayırın. GMT ve UTC farklı insanlar tarafından belirtilmiştir, ancak UTC en sık bahsedilmektedir.

Tüm pratik bilgi işlem amaçları için (neredeyse), UTC aslında GMT'dir. Kesirli bir saniyeye sahip bir zaman damgası görmüyorsanız, GMT ile ilgileniyorsunuz ve bu ayrımı gereksiz kılıyor.

Zaman damgalarını kaydederken yerel saat ofsetini (DST ofseti dahil) olduğu gibi ekleyin.

Bir zaman damgası her zaman GMT'de temsil edilir ve bu nedenle ofseti yoktur.


1
Yerel saat farkı, etkinliğin orijinal "duvar saatini" yeniden oluşturmanıza olanak tanır. Bu ek alanı saklamazsanız, bu veriler kaybolur.
nogridbag

Evet, UTC ve GMT ofsetleri terstir. Örneğin UTC-0700, GMT + 0700 ile aynıdır. Gerçekten, dijital her şey bugünlerde UTC kullanıyor olmalı.
Matt Johnson-Pint

1
@Matt: UTC ve GMT ofsetlerinin ters olduğundan emin misiniz? bunu nereden okuyabilirim?
Reto Höhener

Aslında daha önce yanlış olduğumu düşünüyorum. GMT ve UTC ters çevrilmez. Onları ters olarak gösteren IANA / Olson / TZDB veritabanı gibi uygulamalar var. Buraya bakın . Ofsetleri ters olarak gördüğünüz başka bir alan, javascript'in getTimezoneOffset () işlevindedir.
Matt Johnson-Pint

@MattJohnson: Bunlar hack'lerdir ve kaldırılmalıdır.
Alix Axel

2

İşte benim deneyim: -

(Herhangi bir üçüncü taraf kütüphanesi gerektirmez)

  • Sunucu tarafında, zamanları UTC biçiminde depolayın, böylece veritabanındaki tüm tarih / saat değerleri kullanıcıların, sunucuların, saat dilimlerinin veya DST'nin konumlarına bakılmaksızın tek bir standartta olur.
  • Kullanıcı arayüzü katmanında veya kullanıcıya gönderilen e-postalarda, süreleri kullanıcıya göre göstermeniz gerekir. Bu nedenle, bu uzaklığı, veritabanınızın UTC değerine ekleyebilmeniz için kullanıcının saat dilimi uzaklığına sahip olmanız gerekir. Kaydolduklarında kullanıcının saat dilimi farkını alabilir veya web ve mobil platformlarda otomatik olarak algılayabilirsiniz. Web siteleri için JavaScript'in işlevi getTimezoneOffset () yöntemi, sürüm 1.0'dan beri standarttır ve tüm tarayıcılarla uyumludur. (Ref: http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp )

DST değişikliklerini düşündüğünüzde bu çalışmaz. getTimezoneOffsetçağırdığınız tarih ve saatin ofsetini döndürür. Bu ofset, bir saat dilimi yaz saatine girip çıktığında değişebilir. Saat dilimi wiki'sinde "saat dilimi! = Ofset" konusuna bakın .
Matt Johnson-Pint

1
"10:00 saatinde bir şey yap" gibi bir alarmı saklamak istiyorsanız, DST vardiyaları nedeniyle UTC'de saklayamazsınız. Yerel saate göre depolamanız gerekir.
Alex

2

Tom Scott'un Computerphile kanalında YouTube'daki zaman dilimleri hakkındaki videosu da konunun güzel ve eğlenceli bir açıklamasına sahip. Örnekler:

  • Avustralya ve Yeni Zelanda ile ticareti kolaylaştırmak için Samoa (Pasifik Okyanusu'ndaki bir ada) saat dilimini 24 saat ileriye taşıyor,
  • 2 nüfusun farklı saat dilimlerini takip ettiği Batı Şeria ,
  • 18. yüzyıl, Julian takviminden Gregoryen takvimine (20. yüzyılda Rusya'da gerçekleşti) dönüşür .

1

Aslında, kernel32.dll SystemTimeToTzSpecificLocation dosyasını dışa aktarmaz. Ancak şu iki dışa aktarır: SystemTimeToTzSpecificLocalTime ve TzSpecificLocalTimeToSystemTime ...


1

Asla sadece aşağıdaki gibi inşaatçılara güvenmeyin

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

DST nedeniyle belirli bir tarih olmadığında istisnalar atabilirler. Bunun yerine, bu tür tarihleri ​​oluşturmak için kendi yöntemlerinizi oluşturun. Onlarda, DST nedeniyle oluşan istisnaları yakalayın ve geçiş ofsetiyle gereken zamanı ayarlayın. DST saat dilimine göre farklı tarihlerde ve farklı saatlerde (Brezilya için gece yarısı bile) ortaya çıkabilir.


1

İşleme süresinin açıklanan büyük karışıklık olduğunu ve asla şikayetçi olamayacağınızı kanıtlamak için sadece bir örnek. Bu sayfadaki birkaç noktada artık saniye yok sayıldı.

Birkaç yıl önce, Android işletim sistemi bir UTC zaman referansı almak için GPS uydularını kullandı, ancak GPS uydularının artık saniye kullanmadığı gerçeğini göz ardı etti. Yeni yıl arifesinde, Apple telefonu kullanıcıları ve Android telefonu kullanıcıları yaklaşık 15 saniye arayla geri sayım yaptığında hiç kimse fark etmedi.

Sanırım o zamandan beri düzeltildi, ama bu 'küçük ayrıntıların' size musallat olmak için ne zaman geri geleceğini asla bilemezsiniz.


1
  • Yerel saati hiçbir zaman UTC ofseti (veya saat dilimi referansı) olmadan saklamayın; bunun nasıl struct tmyapılamayacağının örnekleri FAT32 ve C'yi içerir.
  • Bir saat diliminin,
    • bir dizi UTC ofseti (örneğin kışın +0100, yaz aylarında +0200)
    • geçişin ne zaman gerçekleşeceğine dair kurallar (zaman içinde değişebilir: örneğin, 1990'larda AB, geçişi Mart ve Ekim aylarında geçen Pazar günleri 02:00 standart saat / 03: 00 DST'de olduğu gibi uyumlu hale getirdi; daha önce bu farklıydı üye devletler arasında).

Of Bazı uygulamalar struct tmUTC ofsetini depolar, ancak bu standart haline getirmez.


-4

Veritabanları ile uğraşırken (özellikle MySQL , ancak bu çoğu veritabanı için geçerlidir), UTC'yi saklamakta zorlandım.

  • Veritabanları genellikle varsayılan olarak sunucu tarih saatiyle çalışır (CURRENT_TIMESTAMP).
  • Sunucu saat dilimini değiştiremeyebilirsiniz.
  • Saat dilimini değiştirebiliyor olsanız bile, sunucu saat diliminin yerel olmasını bekleyen üçüncü taraf kodunuz olabilir.

Ben sadece sunucu datetime veritabanında depolamak, sonra veritabanı depolanan datetime geri SQL deyimleri (yani, UNIX_TIMESTAMP ()) UTC dönüştürmek için daha kolay buldum. Bundan sonra datetime kodunuzda UTC olarak kullanabilirsiniz.

Sunucu ve tüm kod üzerinde% 100 denetiminiz varsa, sunucu saat dilimini UTC olarak değiştirmek daha iyidir.


"Geri çekilme" tarzı yaz saati geçişleri sırasında yerel saat (sunucu saati) belirsiz olabilir. Açıkladığınız gibi kullanmak güvenilir değildir. Sunucunun yerel saatinin temsil edebileceği birden fazla UTC saati olabilir.
Matt Johnson-Pint

Sunucu aklı başında bir saat diliminde, yani DST yapmayan bir saatte bulunuyorsa, yerel saat mükemmeldir.
sayap
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.