Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What timezone should I use for France to support old and new daylight saving adjustments?

Context

We have a C# program, that deals with time.

We have clients in France, so we convert times to and from France's timezone.

In our C# code : we use Central European Standard Time as a time zone for France.

It describes a timezone, which follows DST changes :

  • on the last sunday of march (3 AM), clocks swicth to summer time are moved forward 1h
  • on the last sunday of october (3 AM), clocks switch to winter time and are moved backward 1h

Our situation

The thing is : France aligned with CEST in 1996 ;
before that date, France would switch from summer time to winter time on the last sunday of september.

Window's CEST timezone describes (accurately) CEST, which happens to not be 100% equivalent to France's timezone for dates before october 1995.

When testing the IANA database (in Windows subsystem for linux), it turns out the Europe/Paris timezone accurately switches time at the end of september for dates < 1995.

Question

is there either :

  • a representation of Europe/Paris timezone in Window's list of standard timezones ?
  • a way to use the IANA database (and Europe/Paris) from C# ?

Sample code we use to convert time to UTC :

using System;
using System.Globalization;

namespace TestingApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var tz = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
            string[] times = {
                // In 1995 :
                //  last sunday in september was  sept. 24th
                //  last sunday in october   was   oct. 29th
                "1995/09/23 12:00:00", "1995/09/24 12:00:00",
                "1995/10/28 12:00:00", "1995/10/29 12:00:00",
            };

            foreach (var t in times) {
                var utc = DateTime.ParseExact(t, "yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None);
                utc = TimeZoneInfo.ConvertTime(utc, tz, TimeZoneInfo.Utc);

                Console.WriteLine(String.Format("Paris: {0} -> UTC: {1}", t, utc.ToString()));
            }
        }
    }
}

// Output :
//  Paris: 1995/09/23 12:00:00 -> UTC: 23/09/1995 10:00:00
//  Paris: 1995/09/24 12:00:00 -> UTC: 24/09/1995 10:00:00  <- instead of 11:00:00 UTC
//  Paris: 1995/10/28 12:00:00 -> UTC: 28/10/1995 10:00:00  <- instead of 11:00:00 UTC
//  Paris: 1995/10/29 12:00:00 -> UTC: 29/10/1995 11:00:00    
like image 488
LeGEC Avatar asked Dec 31 '22 19:12

LeGEC


2 Answers

Is there a way to use the IANA database (and Europe/Paris) from C#?

Yes - use the Noda Time project - for which I'm biased as I'm the main contributor, but one of the big reasons to use it is to support IANA (aka TZDB) time zones.

Here's some sample code to match the code in your question:

using NodaTime;
using System;
using System.Linq;

namespace TestingApp
{
    class Program
    {
        static void Main(string[] args)
        {            
            var tz = DateTimeZoneProviders.Tzdb["Europe/Paris"];

            var localDates = new[]
            {
                new LocalDate(1995, 9, 23),
                new LocalDate(1995, 9, 24),
                new LocalDate(1995, 10, 28),
                new LocalDate(1995, 10, 29)
            };
            var midday = new LocalTime(12, 0, 0);
            var localDateTimes = localDates.Select(date => date.At(midday));

            foreach (var localDateTime in localDateTimes)
            {
                var utc = localDateTime.InZoneStrictly(tz).WithZone(DateTimeZone.Utc);
                Console.WriteLine($"Paris: {localDateTime:yyyy/MM/dd HH:mm:ss} -> UTC: {utc:yyyy/MM/dd HH:mm:ss}");
            }
        }
    }
}
like image 147
Jon Skeet Avatar answered Jan 05 '23 16:01

Jon Skeet


Please, see @JonSkeet solution It's much easier than this one. I don't delete my more complicated answer because this explanation can be useful for someone to understand what's going on with the standart .NET TimeZone.

It's a bit complicated, but possible.

.NET framework uses TimeZoneInfo to define the time change rules. This class has a nested TimeZoneInfo.AdjustmentRule which serves the purpose of defining when the hour changes.

I live in Spain (Europe) so my Windows has installed the european time zone infos. You can get all of the time zone infos of the system by using the method TimeZoneInfo.GetSystemTimeZones().

The only one referring to France, is:

{(UTC+01:00) Bruselas, Copenhague, Madrid, París}

If you examine it, you find only one TimeZoneInfo.AdjustmentRule which defines the current hour change, and not the old one that you need to use:

+ DateStart {01/01/0001 0:00:00} System.DateTime
+ DateEnd   {31/12/9999 0:00:00} System.DateTime
+ DaylightDelta {01:00:00}       System.TimeSpan

- DaylightTransitionStart {System.TimeZoneInfo.TransitionTime} System.TimeZoneInfo.TransitionTime
  Day             1      int
  DayOfWeek       Sunday System.DayOfWeek
  IsFixedDateRule false  bool
  Month           3      int
  + TimeOfDay {01/01/0001 2:00:00} System.DateTime
    Week 5 int

- DaylightTransitionEnd {System.TimeZoneInfo.TransitionTime} System.TimeZoneInfo.TransitionTime
 Day             1      int
 DayOfWeek       Sunday System.DayOfWeek
 IsFixedDateRule false  bool
 Month           10     int
 + TimeOfDay {01/01/0001 3:00:00} System.DateTime
   Week 5 int

So, at least on Spanish Windows (and I suspect on all European Windows) there is no definition of the old rule for hour change in France.

I think that the only solution is to create your own custom time zone and use it in your application TimeZoneInfo.CreateCustomTimeZone Method

When you create this custom time zone info you can include the old adjustment rule: - specify the valid DateStart,DateEnd for the old and new rules - specify the rest of properties for each: DaylightDelta, DaylightTransitionEnd, Day, DayOfweek... and so on, using this one as an example.

I don't know if this rule can be found anywhere, but creating a custom rule would solve your problem.

like image 43
JotaBe Avatar answered Jan 05 '23 16:01

JotaBe