当地时间明天午夜(根据夏令时调整)



我的理解是DateTime.Today给出了当地时区中今天午夜的时间。

DateTime.Today.AddDays(1)总是在当地时区显示明天午夜,还是有时会因为夏令时而关闭?

.AddDays(1) == .AddHours(24),或者它在调整夏令时时有时不同。

如果是.AddDays(1) == .AddHours(24),有没有办法把明天午夜的时间定在当地(可能是23、24或25小时后)?

1。'纯日期时间

关键是要记住,DateTime"只是"一个容器,它容纳了所谓的ticks"自1/10001 12:00am以来经过的100纳秒间隔数">DateTime不保存它所指向的时间指的是哪个时区的信息。

当你调用AddDays时,你实际上是在添加一个常量TicksPerDaytick:

public DateTime AddDays(double value) {
return Add(value, MillisPerDay);
}
private DateTime Add(double value, int scale) {
(...)
return AddTicks(millis * TicksPerMillisecond);
}

AddHours也会导致添加记号。

当您致电AddHours(24)时,您的意思是请将24小时添加到"YYYY-MM-DD HH:MM:SS"(第二天15:00->15:00,与时区或夏令时无关)。您不是在请求24小时后的时间(24小时后可能是14:00或16:00)。

为了回答"24小时后是什么时间?"需要时区信息(请参阅下面的NodaTime)。

同样,AddHours(25)的意思是:请在"YYYY-MM-DD HH:MM:SS"上加1天1小时。DateTime2019年10月12日14:07加上25小时始终为2019年10月份15:07。

请注意,DateTime适用于闰年(只需要静态规则)

2.节点时间

Noda时间允许您"通过"时间,即添加经过的时间量。换句话说,它可以让你回答"n小时后是什么时间?">

在日期和时间算术中,我们可以阅读。

时间线算法非常简单,除了在使用ZonedDateTime时,由于夏令时转换,您可能不会总是得到预期的结果:

DateTimeZone london = DateTimeZoneProviders.Tzdb["Europe/London"];
// 12:45am on March 25th 2012
LocalDateTime local = new LocalDateTime(2012, 3, 25, 0, 45, 00);
ZonedDateTime before = london.AtStrictly(local);
ZonedDateTime after = before + Duration.FromMinutes(20);

我们从当地时间凌晨12点45分开始。我们添加的时间实际上是"经验"时间——就好像我们只等了20分钟一样。然而,当天凌晨1点,欧洲/伦敦时区的时钟提前了一个小时,所以我们的当地时间是凌晨2点05分,而不是你预期的凌晨1点05分。

相反的效果可能发生在另一个夏令时转换时,时钟向后而不是向前:所以凌晨1点45分后的20分钟很容易变成凌晨1点05分!因此,即使我们在ZonedDateTime中公开了"本地时间"的概念,对其执行的任何运算都是使用底层时间线计算的。

我的理解是DateTime.Today在当地时区给出了今天午夜的时间。

这基本上是正确的,但有一个边缘情况。它确实会使用本地时区来确定当前日期,时间设置为00:00:00.0000000。所得到的.Kind将是DateTimeKind.Local。它所做的相当于以下任何一项:

DateTime.Now.Date
DateTime.UtcNow.ToLocalTime().Date
TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local).Date
// etc.

(有关完整列表,请参阅System.DateTime.Now和System.DateTime.Today之间的差异。)

请注意,在我的所有示例中,.Date是最后一个。该属性只是将时间设置为零。它保留.Kind,但不以任何方式对其进行评估。

如果你处理的时区在午夜有一个转换,即时钟从23:5901:00,那么边缘情况就会发挥作用。由于没有00:00,那么来自DateTime.Today的结果将是不存在的本地时间。一个这样的例子是2019-09-08上的智利圣地亚哥。那一天午夜不存在。

DateTime.Today.AddDays(1)总是在当地时区显示明天午夜,还是有时会因为夏令时而关闭?

.AddDays(1) == .AddHours(24),或者它在调整夏令时时有时不同。

AddDaysAddHours函数都不考虑时区。它们都只需加上整整24小时。与.Date属性一样,这些函数保留.Kind,但不会以某种方式对其求值。

如果是.AddDays(1) == .AddHours(24),有没有办法获得当地明天午夜的时间(可能是23、24或25小时后)?

如前所述,请记住午夜可能不存在,您只需要针对这种可能性进行调整。这里有一个仅使用DateTime:的扩展方法

static DateTime AdjustToValidTime(this DateTime dt, TimeZoneInfo tz)
{
if (!tz.IsInvalidTime(dt))
{
// The time is already valid
return dt;
}
// Get the adjustment rule that applies
var rule = tz.GetAdjustmentRules()
.First(x => x.DateStart <= dt && x.DateEnd > dt);
// Get the transition gap.  Often will be one hour, but not always
TimeSpan gap = rule.DaylightDelta;
// Add the gap to adjust to a valid time
return dt.Add(gap);
}

你可以这样使用它(例如):

DateTime tomorrow = DateTime.Today.AddDays(1).AdjustToValidTime(TimeZoneInfo.Local);

如果你想看到一天没有午夜的情况,你可以这样使用:

TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Pacific SA Standard Time");
DateTime today = new DateTime(2019, 9, 8);
DateTime adjusted = today.AdjustToValidTime(tz); // Will be 2019-09-08 01:00

夏令时不会自动调整,您需要根据代码进行调整,然后才能使用

DateTime.Today.AddDays(1)

即使在夏令时下,它也会给你第二天的午夜时间。

正确管理时区和夏令时使用使用Noda time.net库

Noda时间

最新更新