2016-04-08 18 views
9

Çoğumuz zaman aleminde oynayabileceğimizden emin olduğum eğlenceli bir gerçek - geçerli görünen ancak gerçekte bulunmayan tarih/zaman var, ör. Bir gün ışığından yararlanma saati 2:30.Bir tarih/saatin mevcut olup olmadığını belirleme yolu var mı?

Belirli bir tarih/saat belirli bir zaman dilimi belirtiminde geçerli olup olmadığını anlamak için C++ (standart veya Windows) içinde bir yol var mı?

+0

Şaşırtıcı bir soru kesinlikle. Ayrıca, 30-Haziran-2015, 23.59.60 gibi ikinci günleri de desteklemeniz gerekiyor mu? (Öyleyse, Google'ın zaman API'sını kural dışı bırakıyorsa) I * düşünüyorum tarih-zaman kitaplıkları en iyi başlangıç ​​noktası olacaktır.Bu kütüphaneleri kullanıyorum ama bu özel şey için değil. – Bathsheba

+0

"Boost-date-time" ı ve belki de "boost" u etiketledim çünkü bir çözümün bu kutudan çıkmış olabileceğini ya da özellikle bu çerçevede uygulanması zor olamayacağını hayal ettim. – Bathsheba

+0

Standart C++ kütüphanesi zamanla uğraşırken belirsizdir. Windows'ı hedeflerseniz, SystemTimeToFileTime() veya SystemTimeToTzSpecificLocalTime() yöntemini kullanabilirsiniz. Kötü bir tarih geçerken, işlev ERROR_INVALID_PARAMETER ile başarısız olur. Çapraz platform olması gerekiyorsa, bir kütüphane için alışverişe çıkmanız gerekir. –

cevap

0

time_t biçimi (tabii ki kullanılan türü tamsayı sınırları içinde) (1.1.1970 00:00 UTC yana saniye) bir tam sayı değeri çok time_t olası her bir değer mevcut değildir. Öte yandan

değil (eğer gün, ay, yıl, saat, dakika ve saniye için üye) "yapı tm" tüm olası değerleri var (ve bu ne demek istediğini muhtemelen). Bir "struct tm" olup olmadığını kontrol etmek için aşağıdakileri yapmak zorundasınız:

  • tm_isdst üyesini -1 olarak ayarlayın. Bu, DST'nin olup olmadığını bilmediğinizi gösterir.
    • mktime kullanarak bir time_t için "yapı tm" dönüştürme().
    • time_t dosyasını localtime() kullanarak "struct tm" ye dönüştürün.
    • Oluşan "struct tm" öğesini ilk "struct tm" ile karşılaştırın, tm_isdst alanını yok sayın (veya DST'de olup olmadığınızı görmek için kullanın).
+0

Normal zamana geri döndüğünüzde saat 02: 30'da bir değer sağladığınızda, mktime ne yapar? Buradaki problem, takvim zamanının 02: xx saatini iki kez tekrar etmesidir (bir kez dst ile ve bir kez olmadan). Bilgisayarın hangi anlama geldiğini bilmiyorsanız, ya da ... – skyking

+0

Standart, "time_t" nin tamsayı olmasını gerektirmez, aksi halde standardın çözümünüzün işe yarayacağı anlamına gelir. . Gerçekten de uygulama üzerinde çalışacaksa, bir başka soru da ... – skyking

+1

@Skyking: haklısın (kısmen). Saat bir saatliğine geri döndüğünde (DST -> DST olmayan) ve DST'de olup olmadığınızı belirtmiyorsanız, CRT bunu tahmin edecektir, ancak en azından 2 değerini döndüreceğini umuyorum: 30 DST veya 2:30 DST değil. Her neyse, bunu test etmenin en iyi yolu denemek. Sonuç aslında CRT'nin uygulanmasına bağlı olabilir. – Patrick

1

bu free, open-source library kullanarak:

#include "tz.h" 
#include <iostream> 

int 
main() 
{ 
    using namespace date; 
    using namespace std::chrono_literals; 
    try 
    { 
     auto zone = locate_zone("America/New_York"); 
     zone->to_sys(local_days{mar/13/2016} + 2h + 30min); 
    } 
    catch (const std::exception& e) 
    { 
     std::cout << e.what() << '\n'; 
    } 
} 

Bu programın çıktısı: Kısacası

2016-03-13 02:30 is in a gap between 
2016-03-13 02:00:00 EST and 
2016-03-13 03:00:00 EDT which are both equivalent to 
2016-03-13 07:00:00 UTC 

bu program 2016- bir yerel tarih/saat çevirmek için çalışır 03-13 02:30:00 arası "America/New_York" saat dilimini kullanarak UTC'ye. Yerel zaman mevcut olmadığından çeviri bir istisna atar. Yerel saat, gün ışığından itibaren yerel saatin ayarlanması gibi belirsiz ise (farklı bir hata mesajıyla) bir istisna da atılır.

Kütüphane, bu istisna durumlarından kaçınmak için sözdizimi de sağlar.

Bu, VS-2013, VS-2015, clang ve gcc'de çalışır. C++ 11, C++ 14 veya C++ 1z gerektirir.

Yukarıdaki bağlantı belgelere işaret eder. İşte github deposudur:

https://github.com/HowardHinnant/date

0

Windows'a özgün fonksiyonları kullanarak, ilgili zaman aralığına sahip a call toSystemTimeToTzSpecificLocalTime() ardından a call toTzSpecificLocalTimeToSystemTime() yapabilirsiniz. Tamamlandıktan sonra

iki TzSpecificLocalTimeToSystemTime "gerçek" bir zamana geçersiz zaman dönüştürür olarak geçersiz vakit farklı ise.

bool IsValidTime(TIME_ZONE_INFORMATION tz, SYSTEMTIME st) 
{ 
    SYSTEMTIME utcSystemTime, st2; 
    TzSpecificLocalTimeToSystemTime(&tz, &st, &utcSystemTime); 
    SystemTimeToTzSpecificLocalTime(&tz, &utcSystemTime, &st2); 

    return (st != st2); 
} 
İlgili konular