c# - 从通用或本地 DateTime 添加/减去的最佳实践

标签 c# .net datetime timezone dst

我试图在 DateTime 周围添加一个包装器以包含时区信息。这是我到目前为止所拥有的:

public struct DateTimeWithZone {
    private readonly DateTime _utcDateTime;
    private readonly TimeZoneInfo _timeZone;

    public DateTimeWithZone(DateTime dateTime, TimeZoneInfo timeZone) {
        _utcDateTime = TimeZoneInfo.ConvertTimeToUtc(DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified), timeZone);
        _timeZone = timeZone;
    }

    public DateTime UniversalTime { get { return _utcDateTime; } }

    public TimeZoneInfo TimeZone { get { return _timeZone; } }

    public DateTime LocalTime { get { return TimeZoneInfo.ConvertTimeFromUtc(_utcDateTime, _timeZone); } }

    public DateTimeWithZone AddDays(int numDays) {
        return new DateTimeWithZone(TimeZoneInfo.ConvertTimeFromUtc(UniversalTime.AddDays(numDays), _timeZone), _timeZone);
    }

    public DateTimeWithZone AddDaysToLocal(int numDays) {
        return new DateTimeWithZone(LocalTime.AddDays(numDays), _timeZone);
    }
}

这改编自 @Jon Skeet 在之前的问题中提供的答案。

由于夏令时的问题,我正在努力增加/减少时间。根据以下内容,最佳做法是添加/减去世界时:

https://msdn.microsoft.com/en-us/library/ms973825.aspx#datetime_topic3b

我遇到的问题是,如果我说:

var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Romance Standard Time");            
var date = new DateTimeWithZone(new DateTime(2003, 10, 26, 00, 00, 00), timeZone);
date.AddDays(1).LocalTime.ToString();

这将返回 26/10/2003 23:00:00。正如您所看到的,本地时间已经失去了一个小时(由于夏令时结束)所以如果我要显示它,它会说它与刚刚添加一天的那一天是同一天。但是,如果我要说:

date.AddDaysToLocal(1).LocalTime.ToString();

我会在 27/10/2003 00:00:00 回来,时间会保留下来。这在我看来是正确的,但它违背了添加到世界时的最佳实践。

如果有人可以帮助阐明执行此操作的正确方法,我将不胜感激。请注意,我查看了 Noda Time,目前要转换成它需要太多工作,而且我希望更好地理解这个问题。

最佳答案

这两种方式都是正确的(或不正确的)取决于您需要做什么。

我喜欢将这些视为不同类型的计算:

  1. 按时间顺序计算。

  2. 日历计算。

按时间顺序计算涉及以相对于物理时间有规律的单位进行的时间算术。例如添加秒、纳秒、小时或天。

日历 计算涉及以人类认为方便的单位进行的时间算术,但物理时间的长度并不总是相同。例如,添加月份或年份(每个月份的天数不同)。

当你想添加一个不一定有固定秒数的粗略单位,但你仍然想在日期中保留更精细的字段单位,如天、小时、分秒。

在本地时间计算中,您添加了一天,并假定日历计算是您想要的,您保留一天中的本地时间,尽管在本地日历中 1 天并不总是 24 小时。请注意,本地时间的算术有可能导致本地时间有 两个 到 UTC 的映射,或者甚至有 0 个到 UTC 的映射。因此,您的代码应该构造成您知道这种情况永远不会发生,或者能够检测到它何时发生并以适合您的应用程序的任何方式使用react(例如,消除歧义映射)。

在您的 UTC 时间计算(按时间顺序计算)中,您总是添加 86400 秒,并且本地日历可以使用react,但是它可能由于 UTC 偏移变化(与夏令时相关或其他)。 UTC 偏移量变化可能大到 24 小时,因此添加一个按时间顺序排列的日期可能甚至不会使该月的本地日历日增加一个。按时间顺序计算的结果始终具有唯一的 UTC <-> 本地映射(假设输入具有唯一的映射)。

两种计算都很有用。两者都是通常需要的。知道您需要什么,并知道如何使用 API 来计算您需要的任何一个。

关于c# - 从通用或本地 DateTime 添加/减去的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45031306/

相关文章:

c# - 如何将现有项目推到列表末尾?

.net - 套接字异常 : Address already in use

c# - BackgroundWorker RunWorkerCompleted 事件

python - 是否缓存了日期时间对象?

datetime - Sys.setlocale : request to set locale . ..无法兑现

c# - 在 C# 中从自定义 GUI 运行外部命令

c# - jQuery如何在删除属性之前检查属性是否存在

c# - 使用 SqlDataSource 保存图像文件

c# - 如何测试日期时间 (GMT) 是否在 5 分钟内通过?

c# - 获取像素值 "Under"当前窗口