// http://www.cis.temple.edu/~ingargio/cis307/readings/times.c // http://www.lrde.epita.fr/~akim/compil/doc/gnuprog2/Time-Formats.html // http://blogs.missiondata.com/?p=42 #include #include #include #include #include std::ostream & operator<<(std::ostream& os, tm const& d) { return os << " sec=" << d.tm_sec << " min=" << d.tm_min << " hour=" << d.tm_hour << " mday=" << d.tm_mday << " mon=" << d.tm_mon << " year=" << d.tm_year << " wday=" << d.tm_wday << " yday=" << d.tm_yday << " isdst=" << d.tm_isdst; // << " TZ=" << d.tm_zone << " GMTOFF=" << d.tm_gmtoff } tm str2tm(const char* str) { tm tm_struct = { 0 }; char * p = strptime(str, "%FT%T%z %Z", &tm_struct); if (!p) { throw std::runtime_error( std::string("cannot decode")+str); } return tm_struct; } time_t str2time_t(const char* str) { // tzset(); tm tm_struct = str2tm(str); time_t res = mktime(&tm_struct) - _timezone; return res; } void printtm(tm const& date, const char* ctx) { char buffer[80]; strftime(buffer, sizeof(buffer), "%FT%T%z %Z", &date); std::cout << ctx << " = " << buffer // << date << std::endl; } int main (int argc, char **argv) { tzset(); // _reent my_rent; // _tzset_r(&my_rent); { char buffer[80]; timeval tv; gettimeofday(&tv, NULL); struct tm utc; gmtime_r(&tv.tv_sec, &utc); strftime(buffer, sizeof(buffer), "%FT%T%z %Z", &utc); std::cout << "UTC = " << buffer << " DST=" << utc.tm_isdst // << " TZ=" << utc.tm_zone << " GMTOFF=" << utc.tm_gmtoff << std::endl; struct tm local; localtime_r(&tv.tv_sec, &local); strftime(buffer, sizeof(buffer), "%FT%T%z %Z", &local); std::cout << "LOCAL= " << buffer << " DST=" << utc.tm_isdst // << " TZ=" << utc.tm_zone << " GMTOFF=" << utc.tm_gmtoff << std::endl; } std::cout << timezone() << " ; " << _timezone << " ; " << _daylight << " ; " << tzname[0] << std::endl; timeval tv; gettimeofday(&tv, NULL); struct tm utc; gmtime_r(&tv.tv_sec, &utc); printtm(utc, "UTC "); struct tm local; localtime_r(&tv.tv_sec, &local); printtm(local, "LOCAL"); std::cout << "string 2 tm" << std::endl; const char * ch1 = "2006-06-01T21:34:18+0000"; tm tm1 = str2tm(ch1); printtm(tm1, "utc str(2006-06-01T21:34:18+0000)"); std::cout << std::endl; const char * ch2 = "2006-06-01T23:34:18+0500"; tm tm2 = str2tm(ch2); printtm(tm2, "localstr(2006-06-01T23:34:18+0500)"); std::cout << std::endl; std::cout << "string 2 tm 2 time_t 2 tm" << std::endl; time_t t1 = str2time_t(ch1); gmtime_r(&t1, &utc); printtm(utc, "utc str(2006-06-01T21:34:18+0000)"); localtime_r(&t1, &local); printtm(local, "localstr(2006-06-01T21:34:18+0000)"); std::cout << std::endl; time_t t2 = str2time_t(ch2); gmtime_r(&t2, &local); printtm(local, "localstr(2006-06-01T23:34:18+0500)"); std::cout << std::endl; return EXIT_SUCCESS; // MANIPS, Conclusions // A.1- gettimeofday => timeval(time_t) en UTC // A.2- gmtime_r(time_t en UTC) => tm qui se décode en date UTC // A.3- localtime_r(time_t en UTC) => tm qui se décode en date locale // // B.0- Chaine qui exprime une date // B.1- chaine ---{strptime}---> => tm qui se réencode aussitôt en // la chaine // B.2- mktime(tm) considère que tm est une date locale => time_t // en référentiel de date local // => décaler avec -timezone // B.3- Voir A.2- et A.1- pour regénérer les tm locales et UTC // // C.1- strptime ne prend pas en compte les offfsets +0200 // C.2- Décider du tzname[0] et autre tm_isdst semble assez peu // compréhensible, bien que déterministe il semblerait // C.3- le $TZ typique pour la France, semble être // CET-3CEST,M4.1.0/2,M10.5.0/2 // // D.1- Utiliser les TUs avec contexte variable d'eric pour tester // avec divers $TZ // A voir comment rejouer un même test avec plusieurs contextes // différents (TZ non positionné, TZ=UTC, ...) }