我应该为法国使用哪个时区来支持新旧夏令时调整?



>上下文

我们有一个处理时间的C#程序。

我们在法国有客户,所以我们在法国时区之间转换时间。

在我们的 C# 代码中 :我们使用Central European Standard Time作为法国的时区。

它描述了一个时区,它遵循 DST 更改:

  • 在3月的最后一个星期日(凌晨3点),时钟切换到夏令时提前1小时
  • 在 10 月的最后一个星期日(凌晨 3 点),时钟切换到冬令时并向后移动 1 小时

我们的情况

问题是:法国在1996年与CEST结盟;
在此之前,法国将在9月的最后一个星期日从夏令时切换到冬令时。

Window 的CEST时区(准确地)描述了 CEST,它恰好不是 100% 等同于 1995 年 10 月之前的法国时区。

在测试 IANA 数据库(在 Linux 的 Windows 子系统中)时,发现欧洲/巴黎时区准确地将 9 月底的时间切换为 1995 <日期。>

问题

有没有:

  • 在 Windows 的标准时区列表中表示Europe/Paris
  • 时区?
  • 一种从 C# 使用 IANA 数据库(和欧洲/巴黎)的方法?

我们用来将时间转换为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    

有没有办法从 C# 使用 IANA 数据库(以及欧洲/巴黎)?

是的 - 使用 Noda Time 项目 - 我对此有偏见,因为我是主要贡献者,但使用它的一个重要原因是支持 IANA(又名 TZDB)时区。

下面是一些示例代码,用于匹配问题中的代码:

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}");
}
}
}
}

请看@JonSkeet解决方案它比这个容易得多。我不会删除更复杂的答案,因为此解释对于某人了解标准 .NETTimeZone的情况很有用。

这有点复杂,但有可能。

.NET 框架使用TimeZoneInfo来定义时间变化规则。此类具有嵌套TimeZoneInfo.AdjustmentRule用于定义小时何时更改。

我住在西班牙(欧洲),所以我的 Windows 安装了欧洲时区信息。您可以使用方法TimeZoneInfo.GetSystemTimeZones()获取系统的所有时区信息。

唯一提到法国的是:

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

如果检查它,则只会找到一个定义当前小时更改的TimeZoneInfo.AdjustmentRule,而不是需要使用的旧:

+ 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

因此,至少在西班牙Windows上(我怀疑在所有欧洲Windows上)没有定义法国的小时更改旧规则。

我认为唯一的解决方案是创建自己的自定义时区并在您的应用程序中使用它 时区信息.创建自定义时区方法

创建此自定义时区信息时,可以包含旧的调整规则: - 指定新旧规则的有效DateStart,DateEnd- 指定每个属性的其余属性:DaylightDelta, DaylightTransitionEnd, Day, DayOfweek...等等,以这个为例。

我不知道是否可以在任何地方找到此规则,但是创建自定义规则可以解决您的问题。

最新更新