Chr*_*ris 2 c# timezone datetime datetimeoffset nodatime
天然气日定义为欧洲标准时间 24 小时的时间范围,从 UTC 5:00 开始,到次日 UTC 5:00 结束。在欧洲夏令时期间,它从 4:00 UTC 开始,到次日 4:00 UTC 结束(请参阅维基百科或ACER了解英文解释)。
我需要在应用程序中使用天然气日才能执行以下操作:
在我看来,“加油日”应该像时区一样可用,然后我可以在我的应用程序中使用它,但尝试使用DateTime或DateTimeOffset让我完全不知道我应该做什么这项工作。
谁能指出我必须做什么才能进行上面解释的计算的正确方向?是否有一个库可以让这件事变得更容易一些?例如,我已经研究过NodaTime,但我在其文档中找不到任何可以让我更轻松地解决此任务的内容。
我将使用稍微更精确的定义:“Gas Days”(或者更确切地说“Gas Time”,因为这里有时间部分)基于德国当地时区,但移动了 6 小时,这样德国的 06:00 就是 00:燃气时间 00。
正如您在自己的实验中发现的那样,为此实施自定义时区方法并不那么容易,因为所有转换都是相对于德国本地日期和时间发生的,即使气体转换将值推入不同的日期也是如此。(对于 NodaTime 可能可行,但对于 则不行TimeZoneInfo。)
考虑到这一点,您需要在德国时间进行所有转换和操作,然后将它们转移到燃气时间。一些扩展方法在这里可能很有用。解释性注释内嵌在代码中。
public static class GasTimeExtensions
{
private static readonly TimeZoneInfo GermanyTimeZone =
TimeZoneInfo.FindSystemTimeZoneById("Europe/Berlin");
// (use "W. Europe Standard Time" for .NET < 6 on Windows)
private static readonly TimeSpan GasTimeOffset = TimeSpan.FromHours(6);
/// <summary>
/// Adjusts the provided <paramref name="dateTimeOffset"/> to Gas Time.
/// </summary>
/// <param name="dateTimeOffset">The value to adjust.</param>
/// <returns>The adjusted value.</returns>
public static DateTimeOffset AsGasTime(this DateTimeOffset dateTimeOffset)
{
// Convert to Germany's local time.
var germanyTime = TimeZoneInfo.ConvertTime(dateTimeOffset, GermanyTimeZone);
// Shift for Gas Time.
return germanyTime.ToOffset(germanyTime.Offset - GasTimeOffset);
}
/// <summary>
/// Adjusts the provided <paramref name="dateTime"/> to Gas Time.
/// </summary>
/// <param name="dateTime">The value to adjust.</param>
/// <returns>The adjusted value.</returns>
public static DateTime AsGasTime(this DateTime dateTime)
{
// Always go through a DateTimeOffset to ensure conversions and adjustments are applied.
return dateTime.ToGasDateTimeOffset().DateTime;
}
/// <summary>
/// Adjusts the provided <paramref name="dateTime"/> to Gas Time,
/// and returns the result as a <see cref="DateTimeOffset"/>.
/// </summary>
/// <param name="dateTime">The value to adjust.</param>
/// <returns>The adjusted value as a <see cref="DateTimeOffset"/>.</returns>
public static DateTimeOffset ToGasDateTimeOffset(this DateTime dateTime)
{
if (dateTime.Kind != DateTimeKind.Unspecified)
{
// UTC and Local kinds will get their correct offset in the DTO constructor.
return new DateTimeOffset(dateTime).AsGasTime();
}
// Treat the incoming value as already in gas time - we just need the offset applied.
// However, we also need to account for values that might be during DST transitions.
var germanyDateTime = dateTime + GasTimeOffset;
if (GermanyTimeZone.IsInvalidTime(germanyDateTime))
{
// In the DST spring-forward gap, advance the clock forward.
// This should only happen if the data was bad to begin with.
germanyDateTime = germanyDateTime.AddHours(1);
}
// In the DST fall-back overlap, choose the offset of the *first* occurence,
// which is the same as the offset before the transition.
// Otherwise, we're not in a transition, just get the offset.
var germanyOffset = GermanyTimeZone.GetUtcOffset(
GermanyTimeZone.IsAmbiguousTime(germanyDateTime)
? germanyDateTime.AddHours(-1)
: germanyDateTime);
// Construct the Germany DTO, shift to gas time, and return.
var germanyDateTimeOffset = new DateTimeOffset(germanyDateTime, germanyOffset);
return germanyDateTimeOffset.ToOffset(germanyOffset - GasTimeOffset);
}
/// <summary>
/// Add a number of calendar days to the provided <paramref name="dateTimeOffset"/>, with respect to Gas Time.
/// </summary>
/// <remarks>
/// A day in Gas Time is not necessarily 24 hours, because some days may contain a German DST transition.
/// </remarks>
/// <param name="dateTimeOffset">The value to add to.</param>
/// <param name="daysToAdd">The number of calendar days to add.</param>
/// <returns>The result of the operation, as a <see cref="DateTimeOffset"/> in Gas Time.</returns>
public static DateTimeOffset AddGasDays(this DateTimeOffset dateTimeOffset, int daysToAdd)
{
// Add calendar days (with respect to gas time) - not necessarily 24 hours.
return dateTimeOffset.AsGasTime().DateTime.AddDays(daysToAdd).ToGasDateTimeOffset();
}
/// <summary>
/// Add a number of calendar days to the provided <paramref name="dateTime"/>, with respect to Gas Time.
/// </summary>
/// <remarks>
/// A day in Gas Time is not necessarily 24 hours, because some days may contain a German DST transition.
/// </remarks>
/// <param name="dateTime">The value to add to.</param>
/// <param name="daysToAdd">The number of calendar days to add.</param>
/// <returns>The result of the operation, as a <see cref="DateTime"/> in Gas Time.</returns>
public static DateTime AddGasDays(this DateTime dateTime, int daysToAdd)
{
// Add calendar days (with respect to gas time) - not necessarily 24 hours.
return dateTime.AsGasTime().AddDays(daysToAdd).AsGasTime();
}
}
Run Code Online (Sandbox Code Playgroud)
一些用法示例:
转换特定时间戳
var test = DateTimeOffset.Parse("2022-03-22T05:00:00Z").AsGasTime();
Console.WriteLine($"{test:yyyy-MM-ddTHH:mm:sszzz} in Gas Time is
{test.UtcDateTime:yyyy-MM-ddTHH:mm:ssZ} UTC.");
Run Code Online (Sandbox Code Playgroud)
输出:
2022-03-22T00:00:00-05:00 in Gas Time is 2022-03-22T05:00:00Z UTC.
Run Code Online (Sandbox Code Playgroud)
获取当前的gas时间戳
var now = DateTimeOffset.UtcNow.AsGasTime();
Console.WriteLine($"It is now {now:yyyy-MM-ddTHH:mm:sszzz} in Gas Time ({now.UtcDateTime:yyyy-MM-ddTHH:mm:ssZ} UTC).");
Run Code Online (Sandbox Code Playgroud)
输出:
It is now 2022-05-10T14:31:56-04:00 in Gas Time (2022-05-10T18:31:56Z UTC).
Run Code Online (Sandbox Code Playgroud)
添加绝对时间(小时、分钟、秒等)
var start = DateTimeOffset.Parse("2022-03-26T05:00:00Z").AsGasTime();
var end = start.AddHours(24 * 7).AsGasTime(); // add and correct any offset change
Console.WriteLine($"Starting at {start:yyyy-MM-ddTHH:mm:sszzz} Gas Time ({start.UtcDateTime:yyyy-MM-ddTHH:mm:ssZ} UTC),");
Console.WriteLine($"7 x 24hr intervals later is {end:yyyy-MM-ddTHH:mm:sszzz} Gas Time ({end.UtcDateTime:yyyy-MM-ddTHH:mm:ssZ} UTC).");
Run Code Online (Sandbox Code Playgroud)
输出:
Starting at 2022-03-26T00:00:00-05:00 Gas Time (2022-03-26T05:00:00Z UTC),
7 x 24hr intervals later is 2022-04-02T01:00:00-04:00 Gas Time (2022-04-02T05:00:00Z UTC).
Run Code Online (Sandbox Code Playgroud)
添加或减去日历日(由于 DST 转换,并非严格的 24 小时日)
var start = DateTimeOffset.Parse("2022-03-26T05:00:00Z").AsGasTime();
var end = start.AddGasDays(7); // add and correct any offset change
Console.WriteLine($"Starting at {start:yyyy-MM-ddTHH:mm:sszzz} Gas Time ({start.UtcDateTime:yyyy-MM-ddTHH:mm:ssZ} UTC),");
Console.WriteLine($"7 calendar days later is {end:yyyy-MM-ddTHH:mm:sszzz} Gas Time ({end.UtcDateTime:yyyy-MM-ddTHH:mm:ssZ} UTC).");
Run Code Online (Sandbox Code Playgroud)
输出:
Starting at 2022-03-26T00:00:00-05:00 Gas Time (2022-03-26T05:00:00Z UTC),
7 calendar days later is 2022-04-02T00:00:00-04:00 Gas Time (2022-04-02T04:00:00Z UTC).
Run Code Online (Sandbox Code Playgroud)
请注意,在最后两个示例中,我选择了与您不同的日期,以演示跨越 DST 转换。
| 归档时间: |
|
| 查看次数: |
266 次 |
| 最近记录: |