Tomas Svestka
Tomas Svestka

Reputation: 25

c# Convert DateTime from fixed timezone

I'm reading from external API dates like this:

2022-05-13 07:05:00

2022-05-13 13:00:00 ...

These dates are fixed in CET time. I want to convert them into UTC format like "yyyy-MM-ddTHH:mm:sszzz" so I can see UTC offset +02:00.

The problem is that I didn't find a way how to specify that my date is in CET timezone. Functions like ConvertTime, ConvertTimeToUtc doesn't work.

My code is:

    var time = new DateTime(2022,5,26,8,15,00, DateTimeKind.Unspecified);    // 2022-05-26 8:15:00 CET
    TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
    DateTime cet = TimeZoneInfo.ConvertTime(time, tz); // non sense, as no timezone info in time...
    var str = cet.ToString("yyyy-MM-ddTHH:mm:sszzz");

How to resolve this?

Upvotes: 1

Views: 2372

Answers (2)

adamsfamily
adamsfamily

Reputation: 1974

There is a cleaner way of doing it:

public static DateTime ParseCET(string dt)
{
    var cet = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
    var localTime = DateTime.Parse(dt);
    return TimeZoneInfo.ConvertTimeToUtc(localTime, cet);
}

The output is consistent and correct, always respecting daylight saving time period:

// winter time - prints "2/1/2022 11:00:00 AM"
Console.WriteLine(ParseCET("2022-02-01 12:00:00").ToString());

// summer time - prints "8/1/2022 10:00:00 AM"
Console.WriteLine(ParseCET("2022-08-01 12:00:00").ToString());

Edge cases:

  1. When daylight saving time changes from winter to summer time, the clock jumps from 02:00:00 to 03:00:01, therefore there is nothing like 2022-03-27 02:30:00 CET.

In this case according to the documentation and exception is thrown:

If dateTime corresponds to an invalid time, this method throws an ArgumentException.

  1. When daylight saving time changes from summer to winter time, the clock jumps from 03:00:00 to 02:00:01, therefore for instance 2022-10-30 02:30:00 CET could logically translate to either of 00:30:00 UTC or 01:30:00 UTC.

In this case according to the documentation standard (winter) time is assumed:

If dateTime corresponds to an ambiguous time, this method assumes that it is the standard time of the source time zone.

Upvotes: 2

Lightfoe
Lightfoe

Reputation: 350

You can manually set the hours back using:

// Currently CET is ahead of UTC by 2 hours
time = time.AddHours(-2);

And then you can format the date time object without worrying about the time zones.

edit: adding daylight saving.

First you have to check whether you are in the time where daylight saving is in effect or not.

To do this first get the datetime, then check if it is in the daylight saving period. Daylight saving goes into effect at the last sunday of march and is cancelled at the last sunday of october

currentTime = DateTime.Now();
string currentMonth = currentTime.ToString("MM");
string currentDay = currentTime.ToString("DD");

// Daylight saving is in effect
if ( currentMonth > '3' && currentMonth < '10' ) {
    time = time.AddHours(-2);
}

// Daylight saving is not in effect
else if ( currentMonth < '3' || currentMonth > '10' ) {
    time = time.AddHours(-1);
}

    // If it is march or october
else if(currentMonth == '3' || currentMonth == '10')
{

    // Find the last sunday
    var lastSunday = new DateTime(currentTime.Year,currentTime.Month,1);
    lastSunday = lastSunday.AddMonths(1).AddDays(-1);
    while (lastSunday.DayOfWeek != DayOfWeek.Sunday)
    {
        lastSunday = lastSunday.AddDays(-1);
    }
    string sunday = lastSunday.ToString("DD");

     // If it is march, check to see if the day is after or before last sunday
     if(currentMonth == '3'){ 
         if( currentDay > sunday )
         {
             // Daylight saving is in effect
             time = time.AddHours(-2);
         }
         else
         {
             // It is not in effect
             time = time.AddHours(-1);
         }
     }
     // If it is october, check to see if the day is after last sunday or not
     else if(currentMonth == '10'){
         if( currentDay > sunday )
         {
             // Daylight saving is not in effect
             time = time.AddHours(-1);
         }
         else
         {
             // It is in effect
             time = time.AddHours(-2);
         }
     }

}

Upvotes: 0

Related Questions