2011-08-30 13 views
6

verilmemiştir: Bir Alman web çıkarılan bir datetime dizesini ayrıştırmak çalışıyorumAyrıştırma DateTime bilinen ama ayrıştırma tarih ve zaman etrafında bir sorun ile şaşırıp saat dilimini

. ': Dakika 24hours Gün.Ay.Yıl' gibi: Bu formatta verilmiştir

01.01.2011 17:00 

Ve Alman saat diliminde zaman. Ama burada sorunu geliyor:

  • '01 17:00' burada UTC ('01 .01.2011 16:00' ile DateTime yapı için çözümlenen edilmelidir .01.2011, saat dilimi gün ışığı olmadan CET, olduğunu '01 .06.2011 17:00' burada UTC ('01 .01.2011 15:00' ile DateTime yapı için çözümlenen edilmelidir
  • ederken saati), zaman dilimi gün ışığından yararlanma süresi ile)
  • CEST, olduğunu

Bunu nasıl başaracağımı bilmiyorum. Yerel saatimi Almanca saat dilimine ayarlarsam ve DateTime.ParseExact ve bayrağı DateTimeStyles.AssumeLocal ve DateTimeStyles.AdjustToUniversal ile ayrıştırarak doğru şekilde ayrıştırılır. Ancak, herhangi bir müşterinin kendi yerel saatlerinden ve saat dilimlerinden bağımsız olarak ayrıştırmasını istiyorum. Ayrıca, zaman dilimi ofsetini kendim yapmak istemiyorum çünkü bu tarihe bağlı (yaz: -2/kış: -1).

Tarih saatini UTC'ye sahip olduğumda, herhangi bir yerel saat dilimine dönüştürmek kolay olurdu.

+0

olası yinelenen http://stackoverflow.com/questions/246498/creating-a-datetime-in-a-specific-time-zone-in -c-fx-3-5) –

+0

@Michael Haren: Hayır, bir kopyası değil. Bu soruyu sormadan önce bu konuya bir göz attım ve özel sorunuma yardımcı olmadı. –

+0

belki bir çift değil ama ben yardımcı olacağını düşündüm –

cevap

1

görev WP7/Silverlight çerçeve yardımıyla arşivine edilemeyeceğini gördükten sonra evet, bu Noda Time yılında çok daha kolay olacaktır, ben küçük bir yardımcı yazdığı iş vermez:

public static class DateTimeHelper 
{ 
    /// <summary> 
    /// Tries to parse the given datetime string that is not annotated with a timezone 
    /// information but known to be in the CET/CEST zone and returns a DateTime struct 
    /// in UTC (so it can be converted to the devices local time). If it could not be 
    /// parsed, result contains the current date/time in UTC. 
    /// </summary> 
    public static bool TryParseCetCest(string s, string format, IFormatProvider provider, DateTimeStyles style, out DateTime result) 
    { 
     // Parse datetime, knowing it is in CET/CEST timezone. Parse as universal as we fix it afterwards 
     if (!DateTime.TryParseExact(s, format, provider, style, out result)) 
     { 
      result = DateTime.UtcNow; 
      return false; 
     } 
     result = DateTime.SpecifyKind(result, DateTimeKind.Utc); 

     // The boundaries of the daylight saving time period in CET and CEST (_not_ in UTC!) 
     // Both DateTime structs are of kind 'Utc', to be able to compare them with the parsing result 
     DateTime DstStart = LastSundayOf(result.Year, 3).AddHours(2); 
     DateTime DstEnd = LastSundayOf(result.Year, 10).AddHours(3); 

     // Are we inside the daylight saving time period? 
     if (DstStart.CompareTo(result) <= 0 && result.CompareTo(DstEnd) < 0) 
      result = result.AddHours(-2); // CEST = UTC+2h 
     else 
      result = result.AddHours(-1); // CET = UTC+1h 

     return true; 
    } 

    /// <summary> 
    /// Returns the last sunday of the given month and year in UTC 
    /// </summary> 
    private static DateTime LastSundayOf(int year, int month) 
    { 
     DateTime firstOfNextMonth = new DateTime(year, month + 1, 1, 0, 0, 0, DateTimeKind.Utc); 
     return firstOfNextMonth.AddDays(firstOfNextMonth.DayOfWeek == DayOfWeek.Sunday ? -7 : 
                (-1 * (int)firstOfNextMonth.DayOfWeek)); 
    } 
} 

hile olduğunu, (bu TryParseExact tarih UTC ve tarihi dönen/yerel ayarlanır dönüştürülmüş olduğunu varsayalım yapar) olmadan bunu DateTimeStyles.AssumeUniversal bayrağı ayrıştırmak UTC olarak respecifying ve daha sonra manuel olarak bunu actu'ya ayarlayarak al UTC eşdeğeri.

Bu here bulunabilir DST kurallara uyar. Gün ışığından yararlanma saatinin başlangıcından/sonundan hemen önce/sonra tüm 4 sınır durumuyla test ettim. Bu, testin önemini bir kez daha gösterdi: Doğru sonucu üretmesini sağlamak için operatörünü <= olarak değiştirmem gerekti.

(Ben yapmayıistemiyorum olan) burada tekerleği yeniden ediyorum his vardı, ancak bu basit bir iş için ayrılmış bir kütüphane kullanmak istemiyordu. Harika bir proje olan Noda Time'a bir göz attım ama bunun için gerekli olmadığını düşünüyorum.

Ben bu küçük yardımcısı ile birilerine biraz zaman kazandırabilir umuyoruz. Tüm zaman dilimlerinde (örneğin, bunun yerine Noda Time gibi bir lib kullanmanız gerekiyorsa), ancak benim durumumda olduğu gibi sadece tek bir sabit saat dilimine sahip olduğunuz durumlarda, genel olarak jenerik değildir. ([C# fx 3.5 belirli bir süre Bölgesinde bir DateTime oluşturma] arasında

+0

AssumeUniversal'i kullanmadığınıza şaşırdım - zaten bir UTC DateTime ile döndürmeyi * beklerdim *; durum böyle değilse, bu cephede yanıltmak için özür dilerim. DateTime beni rahatsız ediyor :( –

+0

@Jon: dürüst olmak gerekirse tam olarak aynı düşünce ve böyle garip sonuçlar üretmiştir neden bunu beklediğinizden doğru olanı fakat farklı yapar fark kadar merak ediyordu: Eğer '17 ayrıştırmak izin verirsek. : 00 'beklendiği gibi 5 pm UTC varsayar ama benim durumumda (Yerel Timezone = Almanca) saat 7 de bir DateTime struct (Kind = local) döndürür. Eğer '' SpecifyKind (.., Utc) '', bunun üzerine döner, 7:00 Utc struct ... –

+0

Ve evet: DateTime gerçekten sinir bozucu :) –

4

Saat dilimini hangi ayrıştırmayı bilmeniz gerektiğini biliyorsunuz. mantıksal olarak .NET 3.5 (ve dolayısıyla TimeZoneInfo) Eğer gereken varsayarsak:

  • "yerel" zaman olarak ayrıştırma (spesifik olmayan zaman dilimi)
  • dönüştürün bir UTC saat

için yerel saat Ne yazık ki DateTime makes that slightly tricky. EDIT: I DateTimeStyles.AssumeUniversal kullanarak ayrıştırmak istediğiniz düşünebilirsiniz - ancak bu, yerelDateTime döndürerek, annoyingly. Temel olarak ile bitirmek istiyorum doğru zamanda birDateTime kullanabilirsiniz böylece: Eğer gerçekten bir istiyorum

DateTime utc = TimeZoneInfo.ConvertTimeToUtc(parsed, germanTimeZone); 

Not:

parsed = DateTime.SpecifyKind(parsed, DateTimeKind.Unspecified); 

Daha sonra bir UTC değer elde edebilirsiniz önce "belirlenmemiş" tarih zamanı, böylece keyfi bir saat diliminde UTC'ye dönüştürebilirsiniz. Ayrıca, DST değişiklikleri nedeniyle yerel bir zamanın belirsiz olduğunu (iki kez gerçekleştiğini) veya imkansız (hiç gerçekleşmeyecek) olasılığını da hatırlamalısınız.

Ve Bittiğinde :)

+0

+1 Harika, '' ConvertTimeToUtc'' bir şekilde eksik parça oldu. Ancak son bir sorum var: '' germanTimeZone'' nereden geliyor? –

+0

@Philip: Uygun saat dilimi kimliğini çalışıyorsunuz ve 'TimeZoneInfo.FindSystemTimeZoneById' işlevini kullanıyorsunuz. Sanırım "W. Avrupa Standart Saati" ni (standart saat olarak adlandırılan gerçeğini görmezden geliyorsunuz; bu sadece ID'dir - hala gün ışığından yararlanma saatini idare edecektir). –

+0

Muhtemelen, “TimeZoneInfo” 'nun sadece' 'ConvertTime'' yöntemine ve 'Utc'' ve' 'Local'' saat dilimlerine sahip olduğu bir windows phone 7 uygulaması yapıyorum. –

İlgili konular