如何计算 C# 中两个日期之间我所在时区的实际经过时间?
How can I calculate the acutal elapsed time in my timezone between two dates in C#?
我如何计算两个 DateTime
/DateTimeOffset
之间的 实际经过 时间,都在我的时区,采用夏令时,闰年,等等,考虑在内?
例如,以下代码比较 2020 年 3 月 29 日的 00:00 和 05:00 之间的差异,将输出 6 小时的时间跨度(05:00 变为 06:00转换为当地时间,因为夏令时在我的时区开始 02:00,将时钟从 02:00 向前更改为 03:00)。
var timezone = TimeZoneInfo.Local;
var start = new DateTimeOffset(2020, 03, 29, 00, 00, 00, timezone.BaseUtcOffset).LocalDateTime;
var end = new DateTimeOffset(2020, 03, 29, 05, 00, 00, timezone.BaseUtcOffset).LocalDateTime;
var diff1 = end.Subtract(start);
var diff2 = end - start;
Console.WriteLine(diff1); // 06:00:00
Console.WriteLine(diff2); // 06:00:00
我试图在上面的示例中获得 4 小时 的输出,因为这是 00:00 和 05:00 之间经过的时间。
00:00 -> 01:00 (+ 1 hr)
01:00 -> 02:00 (+ 1 hr)
02:00 -> 03:00 (0)
03:00 -> 04:00 (+ 1 hr)
04:00 -> 05:00 (+ 1 hr)
= 4 hrs
我显然在这里遗漏了一些东西。我读过 Comparisons and arithmetic operations with DateTimeOffset values 但无法理解如何进行此计算。
我知道 NodaTime 可能可以做到这一点,但肯定有一种方法可以在没有外部库的情况下做到这一点?
正如Panagiotis Kanavos指出的那样,
So the offset is wrong. It's no longer the BaseUtcOffset, it's a different one
我找到了 TimeZoneInfo.GetUtcOffset 并使用了它。我认为它可以满足我的要求?时区令人困惑,但至少我现在得到了 4 小时的输出。
var timezone = TimeZoneInfo.Local;
var startTime = new DateTime(2020, 03, 29, 00, 00, 00);
var endTime = new DateTime(2020, 03, 29, 05, 00, 00);
var startTimeOffset = timezone.GetUtcOffset(startTime);
var endTimeOffset = timezone.GetUtcOffset(endTime);
var start = new DateTimeOffset(2020, 03, 29, 00, 00, 00, startTimeOffset);
var end = new DateTimeOffset(2020, 03, 29, 05, 00, 00, endTimeOffset);
var diff1 = end.Subtract(start);
var diff2 = end - start;
Console.WriteLine(diff1); // 04:00:00
Console.WriteLine(diff2); // 04:00:00
很好,如果时区没有提供偏移量,这是正确的方法,假设它可以是任意时区。
但是,如果你只使用本地系统时区,你可以简化代码如下:
var start = new DateTimeOffset(new DateTime(2020, 3, 29, 0, 0, 0, DateTimeKind.Local));
var end = new DateTimeOffset(new DateTime(2020, 3, 29, 5, 0, 0, DateTimeKind.Local));
TimeSpan diff = end - start;
这是有效的,因为 DateTime
的 .Kind
属性 在传递到采用单个 DateTime
参数的 DateTimeOffset
构造函数时被评估。如果是 DateTimeKind.Local
或 DateTimeKind.Utc
,则偏移设置正确。只有在 DateTimeKind.Unspecified
的情况下,偏移量可能不正确(因为它将假定为本地,即使情况并非如此)。 See the remarks in the docs here.
我如何计算两个 DateTime
/DateTimeOffset
之间的 实际经过 时间,都在我的时区,采用夏令时,闰年,等等,考虑在内?
例如,以下代码比较 2020 年 3 月 29 日的 00:00 和 05:00 之间的差异,将输出 6 小时的时间跨度(05:00 变为 06:00转换为当地时间,因为夏令时在我的时区开始 02:00,将时钟从 02:00 向前更改为 03:00)。
var timezone = TimeZoneInfo.Local;
var start = new DateTimeOffset(2020, 03, 29, 00, 00, 00, timezone.BaseUtcOffset).LocalDateTime;
var end = new DateTimeOffset(2020, 03, 29, 05, 00, 00, timezone.BaseUtcOffset).LocalDateTime;
var diff1 = end.Subtract(start);
var diff2 = end - start;
Console.WriteLine(diff1); // 06:00:00
Console.WriteLine(diff2); // 06:00:00
我试图在上面的示例中获得 4 小时 的输出,因为这是 00:00 和 05:00 之间经过的时间。
00:00 -> 01:00 (+ 1 hr)
01:00 -> 02:00 (+ 1 hr)
02:00 -> 03:00 (0)
03:00 -> 04:00 (+ 1 hr)
04:00 -> 05:00 (+ 1 hr)
= 4 hrs
我显然在这里遗漏了一些东西。我读过 Comparisons and arithmetic operations with DateTimeOffset values 但无法理解如何进行此计算。
我知道 NodaTime 可能可以做到这一点,但肯定有一种方法可以在没有外部库的情况下做到这一点?
正如Panagiotis Kanavos指出的那样,
So the offset is wrong. It's no longer the BaseUtcOffset, it's a different one
我找到了 TimeZoneInfo.GetUtcOffset 并使用了它。我认为它可以满足我的要求?时区令人困惑,但至少我现在得到了 4 小时的输出。
var timezone = TimeZoneInfo.Local;
var startTime = new DateTime(2020, 03, 29, 00, 00, 00);
var endTime = new DateTime(2020, 03, 29, 05, 00, 00);
var startTimeOffset = timezone.GetUtcOffset(startTime);
var endTimeOffset = timezone.GetUtcOffset(endTime);
var start = new DateTimeOffset(2020, 03, 29, 00, 00, 00, startTimeOffset);
var end = new DateTimeOffset(2020, 03, 29, 05, 00, 00, endTimeOffset);
var diff1 = end.Subtract(start);
var diff2 = end - start;
Console.WriteLine(diff1); // 04:00:00
Console.WriteLine(diff2); // 04:00:00
但是,如果你只使用本地系统时区,你可以简化代码如下:
var start = new DateTimeOffset(new DateTime(2020, 3, 29, 0, 0, 0, DateTimeKind.Local));
var end = new DateTimeOffset(new DateTime(2020, 3, 29, 5, 0, 0, DateTimeKind.Local));
TimeSpan diff = end - start;
这是有效的,因为 DateTime
的 .Kind
属性 在传递到采用单个 DateTime
参数的 DateTimeOffset
构造函数时被评估。如果是 DateTimeKind.Local
或 DateTimeKind.Utc
,则偏移设置正确。只有在 DateTimeKind.Unspecified
的情况下,偏移量可能不正确(因为它将假定为本地,即使情况并非如此)。 See the remarks in the docs here.