skip to Main Content

I have code that converts long numbers to dates.

 DateTimeOffset value =
   DateTimeOffset.FromUnixTimeSeconds(1597325462);
   DateTime showTime = value.DateTime;
   string easternZoneId = "America/New_York";
   TimeZoneInfo easternZone =
       TimeZoneInfo.FindSystemTimeZoneById(easternZoneId);
   DateTime targetTime =
       TimeZoneInfo.ConvertTime(showTime, easternZone);
   Console.WriteLine("DateTime is {0}", targetTime);

On my Mac, the output is "DateTime is 8/13/2020 6:31:02 AM"
On my server the output is "DateTime is 8/13/2020 9:31:02 AM"

Identical code on both.

The Linux box value is accurate. How can I get the same result on my Mac?

2

Answers


  1. The issue seems to be that there is not such a timezone I’d in the ICU library that both OS look into.

    Check the example in the Microsoft docs:
    https://learn.microsoft.com/en-us/dotnet/api/system.timezoneinfo.converttimebysystemtimezoneid?view=netcore-3.1

    DateTime currentTime = DateTime.Now;
    Console.WriteLine("New York: {0}", 
                TimeZoneInfo.ConvertTimeBySystemTimeZoneId(currentTime, TimeZoneInfo.Local.Id, "Eastern Standard Time"));
    

    So it looks like the id you should look for is ""Eastern Standard Time"

    If you can’t find it then run the following code to check the available timezones on your pc

    foreach (TimeZoneInfo z in TimeZoneInfo.GetSystemTimeZones())
                    Console.WriteLine(z.Id);
    

    The destinationTimeZoneId parameter must correspond exactly to the time zone’s identifier in length, but not in case, for a successful match to occur; that is, the comparison of destinationTimeZoneId with time zone identifiers is case-insensitive.

    So check the timezones and copy the correct string to use based on what exists on the machine.

    Login or Signup to reply.
  2. The overload of TimeZone.ConvertTime you’re using takes a DateTime value and a destination TimeZoneInfo. There’s no mention of the source time zone, so it is infered from the .Kind property of the DateTime being passed in.

    In your case, that is DateTimeKind.Unspecified, because the .DateTime property of a DateTimeOffset always returns unspecified, regardless of what the offset is.

    In the ConvertTime call, if the kind is DateTimeKind.Unspecified, it is assumed to be local time (as if it were DateTimeKind.Local). (Scroll down to the Remarks section in the docs here.) Thus, you are converting as if the Unix timestamp were local-time based, rather than the actuality that it is UTC based. You get different results between your workstation and server because they have different system-local time zones – not because they are running different operating systems.

    There are a number of different ways to rewrite this to address the problem. I will give you a few to choose from, in order of my preference:

    • You could leave everything as a DateTimeOffset throughout the conversion process:

      DateTimeOffset value = DateTimeOffset.FromUnixTimeSeconds(1597325462);
      string easternZoneId = "America/New_York";
      TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId);
      DateTimeOffset targetTime = TimeZoneInfo.ConvertTime(value, easternZone);
      
    • You could use the .UtcDateTime property instead of the .DateTime property:

      DateTimeOffset value = DateTimeOffset.FromUnixTimeSeconds(1597325462);
      DateTime showTime = value.UtcDateTime;
      string easternZoneId = "America/New_York";
      TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId);
      DateTime targetTime = TimeZoneInfo.ConvertTime(showTime, easternZone);
      
    • You could use ConvertTimeFromUtc instead of ConvertTime:

      DateTimeOffset value = DateTimeOffset.FromUnixTimeSeconds(1597325462);
      DateTime showTime = value.DateTime;
      string easternZoneId = "America/New_York";
      TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId);
      DateTime targetTime = TimeZoneInfo.ConvertTimeFromUtc(showTime, easternZone);
      
    • You could specify UTC as the source time zone in the ConvertTime call:

      DateTimeOffset value = DateTimeOffset.FromUnixTimeSeconds(1597325462);
      DateTime showTime = value.DateTime;
      string easternZoneId = "America/New_York";
      TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById(easternZoneId);
      DateTime targetTime = TimeZoneInfo.ConvertTime(showTime, TimeZoneInfo.Utc, easternZone);
      

    There are a few other options, such as explicitly setting the kind, but I think the above gives you enough to go on.

    If in doubt, pick the first option. DateTimeOffset is much easier to rationalize than DateTime in most cases.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search