野田时间倒计时

时间:2014-12-17 01:07:00

标签: c# countdown nodatime

我已经写了一份申请,以显示下一次大型行业贸易展的剩余时间 (在撰写本文时将来约两年)

我开始使用标准的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;
}

所以问题就变成了:

从现在到某个日期,你如何获得剩余时间?

2 个答案:

答案 0 :(得分:2)

要确定两个事件之间的“日历”时间量,您需要Period,因为您已经发现了。但是,处理本地日期和时间。

要确定两个事件之间的“日历中立”时间量,您可以使用InstantDuration - 但是您无法显示剩余的月数。

这两种方法都有缺点,但基本上它们是时间运作方式的基础。如果您使用本地时间方法,那么您将发现在经过DST转换时,时间将向后或向前跳一小时。如果您使用即时方法,则仅限于几天/几个月/小时/分钟等 - 而不是几个月。

两者之间的一个选项是使用LocalDateTimePeriod,但是以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);
    }

the result


如果任何人有一个解决方案,在采取时区(本地与发生事件的地方)的同时考虑这一点,这将是非常棒的。 (我尝试以类似的方式使用ZonedDateTime进行此操作,但遇到了一堵砖墙)。

此外,我不清楚这种方法是否考虑了月中的各个日子,夏令时,闰年等。有人知道吗? 如果不是,显然我会欢迎任何优雅的解决方案。