簡體   English   中英

Noda Time - 帶區域的開始/結束日期

[英]Noda Time - Start/end of day with zone

在代碼運行的系統上設置的時區中,獲取ZonedDateTime(表示當前日期的開始和結束)的正確和更簡潔的方法是什么?

以下代碼是不是太復雜了?

ZonedDateTime nowInZone = SystemClock.Instance.Now.InZone(DateTimeZoneProviders.Bcl.GetSystemDefault());

ZonedDateTime start = new LocalDateTime(nowInZone.Year, nowInZone.Month, nowInZone.Day, 0, 0, 0).InZoneStrictly(DateTimeZoneProviders.Bcl.GetSystemDefault());

ZonedDateTime end = new LocalDateTime(nowInZone.Year, nowInZone.Month, nowInZone.Day, 23, 59, 59).InZoneStrictly(DateTimeZoneProviders.Bcl.GetSystemDefault());

鑒於這些值,我需要測試另一個ZonedDateTime是否在它們之間。

DateTimeZone對象上的AtStartOfDay值具有您正在尋找的魔力。

// Get the current time
IClock systemClock = SystemClock.Instance;
Instant now = systemClock.Now;

// Get the local time zone, and the current date
DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
LocalDate today = now.InZone(tz).Date;

// Get the start of the day, and the start of the next day as the end date
ZonedDateTime dayStart = tz.AtStartOfDay(today);
ZonedDateTime dayEnd = tz.AtStartOfDay(today.PlusDays(1));

// Compare instants using inclusive start and exclusive end
ZonedDateTime other = new ZonedDateTime(); // some other value
bool between = dayStart.ToInstant() <= other.ToInstant() &&
               dayEnd.ToInstant() > other.ToInstant();

幾點:

  • 最好養成將時鍾實例與調用Now分開的習慣。 這使得在單元測試后更容易更換時鍾。

  • 您只需要獲取一次本地時區。 我更喜歡使用Tzdb提供程序,但任何一個提供程序都可以用於此目的。

  • 在一天結束時,最好使用第二天的開始。 這可以防止您不得不處理粒度問題,例如是否應該采取23:59,23:59:59,23:59.999,23:59:59.9999999等。此外,它使得更容易獲得整數做數學的結果。

    通常,日期+時間范圍(或僅時間范圍)應視為半開區間[start,end) - 而僅日期范圍應視為完全關閉區間[start,end]

  • 因此,將開始與<=進行比較,但將結果與>進行比較。

  • 如果您確定其他ZonedDateTime值位於同一時區並使用相同的日歷,則可以省略對ToInstant的調用,並直接比較它們。

更新

正如Jon在評論中提到的, Interval類型可能是一個有用的便利。 它已經設置為使用半開放的Instant值。 以下函數將獲取特定時區中當前“日期”的間隔:

public Interval GetTodaysInterval(IClock clock, DateTimeZone timeZone)
{
    LocalDate today = clock.Now.InZone(timeZone).Date;
    ZonedDateTime dayStart = timeZone.AtStartOfDay(today);
    ZonedDateTime dayEnd = timeZone.AtStartOfDay(today.PlusDays(1));
    return new Interval(dayStart.ToInstant(), dayEnd.ToInstant());
}

像這樣調用它(使用上面相同的值):

Interval day = GetTodaysInterval(systemClock, tz);

現在可以使用Contains函數進行比較:

bool between = day.Contains(other.ToInstant());

請注意,您仍然必須轉換為Instant ,因為Interval類型不能Interval時區。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM