[英]Noda Time Countdown
我已經編寫了一個應用程序,以顯示下一次大型行業展會之前的剩余時間。
(在撰寫本文時大約是兩年)
我開始使用標准的DateTime
類,但很快遇到了每個月處理不同天數的問題,2016年是Le年,其中包含Le日 ,夏時制等。
幸運的是,我發現了NodaTime 。 (感謝@JonSkeet)
不用說,我習慣使用DateTime的方式並不適用,而且我很難確定如何獲得剩余時間。 (周圍沒有很多例子)
例如,以下代碼不起作用,因為您無法從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;
}
所以問題變成了:
要確定兩個事件之間的“日歷”時間量,您需要已發現的Period
。 但是,這僅處理本地日期和時間。
要確定兩個事件之間的“日歷中立”時間量,可以使用“ Instant
和“ Duration
-但是您無法顯示剩余的月數。
這兩種方法都有缺點,但是基本上它們是時間工作方式的基礎。 如果您使用本地時間方法,那么您會發現,經過DST轉換后,時間量會向后或向前跳一個小時。 如果您使用即時方法,則只能使用天/月/小時/分鍾等信息,而不是月份。
兩者之間的一種選擇是使用LocalDateTime
和Period
,但是將事件和當前時間都錨定在UTC中。 這樣一來,就不會有間斷,因為UTC實際上是不變的基准線。 這也意味着無論您在櫃台上的哪個位置(或托管代碼,具體取決於您打算做什么),您都將始終顯示相同的“剩余時間”。
如果您想了解有關為什么為什么不能在兩個ZonedDateTime
值之間獲得Period
更多詳細信息,我可以考慮一些根本有問題的示例。 最重要的是,日歷計算和時區不能很好地配合使用...
僅給出一些實際的代碼,我會得到一些類似的信息:
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
並對其調用GetCurrentLocalDateTime
。
我最終使用的解決方案是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
進行此操作,但遇到了磚牆)。
另外,我不清楚這種方法是否考慮了每月的各個天,夏時制,leap年等。 有人知道嗎
如果不是這樣,顯然我會歡迎任何優雅的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.