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 :
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 :
Europe/Paris
timezone in Window's list of standard timezones ?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
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}");
}
}
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With