2016-04-08 18 views
9

Il fatto di sapere che molti di noi sanno giocare nei reame del tempo sanno che ci sono date/orari che possono sembrare validi ma che in realtà non esistono, ad es. 2:30 AM su un orario di commutazione dell'ora legale.C'è un modo per determinare se una data/ora non esiste?

C'è un modo in C++ (standard o Windows) per capire se una determinata data/ora è valida in una data specifica del fuso orario?

+0

Una domanda intrigante, certamente. Hai anche bisogno di supportare il secondo giorno bisestile, come il 30 giugno 2015, 23.59.60? (Se è così che esclude l'API temporale di Google) I * think * incrementa le librerie date-time sarebbe il miglior punto di partenza.Io uso quelle librerie ma non per questa particolare cosa. – Bathsheba

+0

Ho taggato "boost-date-time" e, forse con cattiveria, "boost" poiché immagino che una soluzione possa essere disponibile per questo fuori dalla scatola, o non particolarmente difficile da implementare in quel framework. – Bathsheba

+0

La libreria C++ standard non è adatta a gestire il tempo. Se scegli come target Windows, puoi utilizzare SystemTimeToFileTime() o SystemTimeToTzSpecificLocalTime(). Il superamento di una data errata rende la funzione fallita con ERROR_INVALID_PARAMETER. Se deve essere multipiattaforma, devi andare a fare shopping per una biblioteca. –

risposta

0

Il formato time_t è un valore intero (secondi da 1/1/1970 00:00 UTC), quindi ogni possibile valore di time_t esiste (entro i limiti del tipo intero utilizzato ovviamente).

D'altra parte, non tutti i possibili valori di "struct tm" (dove si hanno membri per giorno, mese, anno, ora, minuto e secondo) esistono (e questo è probabilmente ciò che si intende). Per verificare se esiste una "struct tm", è necessario effettuare le seguenti operazioni:

  • Impostare il membro tm_isdst su -1. Questo indica che non si sa se la sua ora legale o meno.
    • Convertire la "struct tm" in time_t utilizzando mktime().
    • Converti time_t in "struct tm" utilizzando localtime().
    • Confrontare la "struct tm" risultante con la "struct tm" iniziale, ignorare il campo tm_isdst (o utilizzarlo per vedere se si è in DST o no).
+0

Che cosa fa 'mktime' se fornisci un valore alle 02:30 quando torni al normale? Il problema qui è che l'ora del calendario ripeterebbe l'ora 02: xx due volte (una volta con dst e una volta senza). Se non sai cosa intendi, probabilmente il computer non può dirti neanche ... – skyking

+0

Lo standard non richiede che 'time_t' sia un numero intero, ma altrimenti sembra che lo standard implicherebbe che la tua soluzione funzionasse . Se effettivamente funzionerà sull'implementazione è un'altra domanda ... – skyking

+1

@Skyking: hai ragione (parzialmente). Quando l'orologio è arretrato per un'ora (DST -> non-DST), e non stai specificando se sei in DST o no, il CRT indovina, ma almeno spero che possa restituire o 2: 30 ora legale o 2:30 non-ora legale. Ad ogni modo, il modo migliore per provarlo è provarlo. Il risultato potrebbe effettivamente dipendere dall'implementazione del CRT. – Patrick

1

Utilizzando questo free, open-source library:

#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'; 
    } 
} 

L'uscita di questo programma è:

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 

In breve, questo programma tenta di tradurre una data locale/ora 2016- 03-13 02:30:00 UTC utilizzando il fuso orario "America/New_York". La traduzione genera un'eccezione perché l'ora locale non esiste. Viene generata anche un'eccezione (con un messaggio di errore diverso), se l'ora locale è ambigua, ad esempio quando si ripristina l'orologio locale dall'ora legale.

La libreria fornisce anche la sintassi per evitare queste eccezioni se questo è il desiderio.

Questo funziona su VS-2013, VS-2015, clang e gcc. Richiede C++ 11, C++ 14 o C++ 1z.

Il collegamento sopra indica la documentazione. Ecco il repository GitHub:

https://github.com/HowardHinnant/date

0

Utilizzando le funzioni specifiche di Windows, è possibile effettuare a call toTzSpecificLocalTimeToSystemTime() seguita da a call toSystemTimeToTzSpecificLocalTime() al fuso orario di riferimento.

Al termine, se i due differiscono hai un tempo non valido come TzSpecificLocalTimeToSystemTime converte il tempo non valido in un tempo "reale".

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

    return (st != st2); 
}