Caduchon
Caduchon

Reputation: 5201

Detect daylight saving time algorithm

I wrote a class Instant managing date and time with respect to timezones and some daylight saving time algorithms (Europe and USA). Until now, I let the user of the class specify the DST algorithm with Europe as default value. But now I want to detect it automatically for the default value.

This is my first implementation. It seems working on my Windows 7 workstation (compiler: intel 14.0) (I juste have to clarify the list), but it doesn't work on Linux openSUSE (compiler: gcc 4.8.3) because tz.tz_dsttime is always 0.

typedef enum {
    DST_ALGO_NONE   = 0,
    DST_ALGO_EUROPE = 1,
    DST_ALGO_USA    = 2
} TimeZoneType;

TimeZoneType auto_detect_dst_algorithm()
{
#   ifdef WIN32
        TIME_ZONE_INFORMATION tz;
        GetTimeZoneInformation(&tz);
        std::wstring tz_wstr = tz.DaylightName;
        std::string tz_str(tz_wstr.begin(), tz_wstr.end());
        if(   tz_str.find("Romance") != std::string::npos
           || tz_str.find("RST") != std::string::npos
           || tz_str.find("Central Europe") != std::string::npos
           || tz_str.find("CEST") != std::string::npos
           || tz_str.find("Middle Europe") != std::string::npos
           || tz_str.find("MET") != std::string::npos
           || tz_str.find("Western Europe") != std::string::npos
           || tz_str.find("WET") != std::string::npos )
        {
            return DST_ALGO_EUROPE;
        }
        else if(   tz_str.find("Pacific") != std::string::npos
                || tz_str.find("PDT") != std::string::npos )
        {
            return DST_ALGO_USA;
        }
        else
        {
            return DST_ALGO_NONE;
        }
#   else
        struct timeval tv;
        struct timezone tz;
        gettimeofday(&tv, &tz);
        if(tz.tz_dsttime == 1)
        {
            return DST_ALGO_USA;
        }
        else if(tz.tz_dsttime == 3 || tz.tz_dsttime == 4)
        {
            return DST_ALGO_EUROPE;
        }
        else
        {
            return DST_ALGO_NONE;
        }
#   endif
}

What is the good way to do that ?

Upvotes: 0

Views: 1205

Answers (1)

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241563

From the gettimeofday man page:

On Linux, with glibc, the setting of the tz_dsttime field of struct timezone has never been used by settimeofday() or gettimeofday(). Thus, the following is purely of historical interest.

On old systems, the field tz_dsttime contains a symbolic constant...

... Of course it turned out that the period in which Daylight Saving Time is in force cannot be given by a simple algorithm, one per country; indeed, this period is determined by unpredictable political decisions. So this method of representing timezones has been abandoned.

The comments in the original question are correct. You should not be trying to implement this yourself, especially using an abandoned API.

Even in the Windows portion of your sample code, you're making a lot of assumptions about what things you might find in the DaylightName field. You do realize there are many more time zones than the ones you're testing for, right? Also, these strings will come out quite differently on a system where the user has selected a primary language other than English.

There are many good time zone libraries for C++. Anything worthwhile is going to be using the IANA tz database as its source. I'd take a good look at the best practices FAQ, and the timezone tag wiki. In particular, the FAQ recommends CCTZ, ICU, or TZ, and warns against using Boost for this functionality.

Upvotes: 1

Related Questions