我已经写了一份申请,以显示下一次大型行业贸易展的剩余时间 (在撰写本文时将来约两年)
我开始使用标准的DateTime
课程,但很快就遇到了每月处理不同天数的问题,2016年是闰年,包含Leap Day,夏令时等
谢天谢地,我发现了NodaTime。 (谢谢@JonSkeet)
不幸的是,我习惯使用DateTime的方式并不适用,而且我很难弄清楚如何节省时间。 (周围没有很多例子)
例如,以下代码无效,因为您无法从instant中减去LocalDateTime:
void example()
{
DateTime DT = Convert.ToDateTime("09/12/2016 10:00AM");
LocalDateTime NodaLocalDateTime = new LocalDateTime(
DT.Year, DT.Month, DT.Day, DT.Hour, DT.Minute, 0);
Period P = NodaLocalDateTime - SystemClock.Instance.Now;
}
所以问题就变成了:
答案 0 :(得分:2)
要确定两个事件之间的“日历”时间量,您需要Period
,因为您已经发现了。但是,仅处理本地日期和时间。
要确定两个事件之间的“日历中立”时间量,您可以使用Instant
和Duration
- 但是您无法显示剩余的月数。
这两种方法都有缺点,但基本上它们是时间运作方式的基础。如果您使用本地时间方法,那么您将发现在经过DST转换时,时间将向后或向前跳一小时。如果您使用即时方法,则仅限于几天/几个月/小时/分钟等 - 而不是几个月。
两者之间的一个选项是使用LocalDateTime
和Period
,但是以UTC结合事件和当前时间。这样就永远不会出现不连续性,因为UTC是一条不变的基线。这也意味着你总是会显示相同数量的“剩余时间”,无论你在世界的哪个地方看到柜台(或托管代码,具体取决于你打算做什么)。
如果您想了解有关为什么的更多详细信息,则无法在两个Period
值之间获得ZonedDateTime
,我可以考虑一些基本上存在问题的示例。最重要的是,日历算术和时区虽然不能很好地协同工作......
只是提供一些实际的代码,我会有类似的东西:
public sealed class EventCountdown
{
private readonly LocalDateTime eventTimeUtc;
private readonly IClock clock;
// It's probably most convenient to express the event time with the time zone
// in which it occurs. You could easily change this though.
public EventCountdown(ZonedDateTime zonedEventTime, IClock clock)
{
this.eventTimeUtc = zonedEventTime.WithZone(DateTimeZone.Utc).LocalDateTime;
this.clock = clock;
}
public Period GetPeriodRemaining()
{
return Period.Between(clock.Now.InUtc().LocalDateTime, eventTimeUtc);
}
}
请注意,在Noda Time 2.0中,IClock.Now
属性正在更改为GetCurrentInstant
方法...但在这种情况下,您可能在UTC中使用ZonedClock
并调用{ {1}}就可以了。
答案 1 :(得分:1)
我最终使用的解决方案是Period.Between()
,这似乎可以解决问题。
using NodaTime;
DateTime EventDT;
LocalDateTime LocalizedEventDT;
Period TimeLeft;
public EventCountdown()
{
// Start with a date and time
EventDT = Convert.ToDateTime("09/12/2016 10:00AM");
// Localize it
LocalizedEventDT = new LocalDateTime(
EventDT.Year, EventDT.Month,
EventDT.Day, EventDT.Hour,
EventDT.Minute, 0);
}
// find out how much time is between now and the future date
public Period GetPeriodRemaining()
{
DateTime dt_Now = DateTime.Now;
return Period.Between(new LocalDateTime(
dt_Now.Year, dt_Now.Month, dt_Now.Day, dt_Now.Hour,
dt_Now.Minute, dt_Now.Second), LocalizedEventDT);
}
如果任何人有一个解决方案,在采取时区(本地与发生事件的地方)的同时考虑这一点,这将是非常棒的。 (我尝试以类似的方式使用ZonedDateTime
进行此操作,但遇到了一堵砖墙)。
此外,我不清楚这种方法是否考虑了月中的各个日子,夏令时,闰年等。有人知道吗? 如果不是,显然我会欢迎任何优雅的解决方案。