0
votes

Puerto Rico and several other countries do not have a daylight savings time. I don't see a way to specify whether or not a given country/locale supports daylight savings time using the TimeZoneInfo class.

DateTime dt = DateTime.UtcNow;        
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Atlantic Standard Time");
if (tz.IsDaylightSavingTime(dt))
    Console.WriteLine("Daylight Savings");

About the only thing I can think of is to allow the user to specify both the Time Zone and also whether to adjust for Daylight Savings, and then use TimeZoneInfo.GetUtcOffset instead of the more direct TimeZoneInfo.ConvertTimeFromUtc method.

    if (tz.IsDaylightSavingTime(dt) && !supportsDaylightSaving)
    {
        var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero).AddHours(-1);
        var dt3 = utcOffset.ToOffset(tz.GetUtcOffset(utcOffset)).DateTime;
        Console.WriteLine(dt3);
    }

Any other approaches to consider? Anything bad about the above approach?

2
DST conformance is a local political decision. Lots of other locales in the USA that don't follow it, American Indian tribal lands, counties in Indiana and Arizona, etc. Only the local PC in such a locale knows about that. TimeZoneInfo can only give you the best guess. Always use UTC to avoid these kind of traps.Hans Passant
Agreed 100%, Hans, and the data is stored in UTC. But for display, I need to display local time. I'm beginning to think the approach I outlined above is my best bet as it will take care of letting the user tell me about the exceptional cases (the app is an MVC app, so "Local" is no good since the server would be the timezone I would reference).danmiser
Displaying local time on a local PC is never a problem, it knows the rules. The only possible mistake you could make is making the conversion on a non-local PC. Of course you would never make the mistake of forcing a web server to be aware of locality, that cannot ever work. They only know what the inside of a server room looks like.Hans Passant

2 Answers

1
votes

The correct Id to use with TimeZoneInfo for Puerto Rico is "SA Western Standard Time".

It has a DisplayName of "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", and does not follow daylight saving time. It's easy to miss, but "San Juan" in the display name does indeed refer to San Juan, Puerto Rico.

There are actually very few locations that don't have a distinct time zone ID in the Windows time zone data. Some do exist, and for those you would have to create a fixed offset zone. An example would be Atikokan, Canada - which is on Eastern Time, but does not use DST.

If you're concerned at that level, you should probably switch to IANA time zones, which you can easily do using Noda Time.

If you're ever in doubt as to which Windows time zone should be selected, you can always compare the IANA time zone to the CLDR mappings. Indeed, it shows that "America/Puerto_Rico" is one of the possible translations of "SA Western Standard Time".

0
votes

Actually there is SupportsDaylightSavingTime property which indicates whether DST is used or not by the time zone. For example:

ReadOnlyCollection<TimeZoneInfo> zones = TimeZoneInfo.GetSystemTimeZones();
foreach(TimeZoneInfo zone in zones)
{
   if (! zone.SupportsDaylightSavingTime)
      Console.WriteLine(zone.DisplayName);
}

prints all time zones that do not have DST.

If Puerto Rico doesn't have it's own time zone, next best option is to find matching time zone (i.e. same offset and without DST) and use it. If no such zone exist, just use UTC and apply constant offset.