2014-06-23 20 views
8

Làm cách nào để có được ngày bắt đầu và ngày kết thúc cho Giờ tiết kiệm ánh sáng ban ngày bằng cách sử dụng Thời gian Noda? Hàm dưới đây hoàn thành nhiệm vụ này nhưng nó khó sử dụng và đòi hỏi một giải pháp đơn giản hơn.Thời gian Tiết kiệm Ánh sáng ban ngày Bắt đầu và Kết thúc ở NodaTime

/// <summary> 
/// Gets the start and end of daylight savings time in a given time zone 
/// </summary> 
/// <param name="tz">The time zone in question</param> 
/// <returns>A tuple indicating the start and end of DST</returns> 
/// <remarks>Assumes this zone has daylight savings time</remarks> 
private Tuple<LocalDateTime, LocalDateTime> GetZoneStartAndEnd(DateTimeZone tz) 
{ 
    int thisYear = TimeUtils.SystemLocalDateTime.Year; // Get the year of the current LocalDateTime 

    // Get January 1, midnight, of this year and next year. 
    var yearStart = new LocalDateTime(thisYear, 1, 1, 0, 0).InZoneLeniently(tz).ToInstant(); 
    var yearEnd = new LocalDateTime(thisYear + 1, 1, 1, 0, 0).InZoneLeniently(tz).ToInstant(); 

    // Get the intervals that we experience in this year 
    var intervals = tz.GetZoneIntervals(yearStart, yearEnd).ToArray(); 

    // Assuming we are in a US-like daylight savings scheme, 
    // we should see three intervals: 
    // 1. The interval that January 1st sits in 
    // 2. At some point, daylight savings will start. 
    // 3. At some point, daylight savings will stop. 
    if (intervals.Length == 1) 
     throw new Exception("This time zone does not use daylight savings time"); 
    if (intervals.Length != 3) 
     throw new Exception("The daylight savings scheme in this time zone is unexpected."); 

    return new Tuple<LocalDateTime,LocalDateTime>(intervals[1].IsoLocalStart, intervals[1].IsoLocalEnd); 
} 

Trả lời

6

Không có một built-in chức năng duy nhất mà tôi biết, nhưng dữ liệu là tất cả ở đó, vì vậy bạn chắc chắn có thể tạo riêng của bạn.

Bạn đang đi đúng với những gì bạn đã thể hiện, nhưng có một vài điều cần xem xét:

  • người thường quan tâm đến cuối điểm của chu kỳ. Bằng cách trả lại bắt đầu và dừng chỉ khoảng giữa, bạn có thể nhận được các giá trị khác với bạn mong đợi. Ví dụ: nếu bạn sử dụng một trong các múi giờ của Hoa Kỳ, chẳng hạn như "America/Los_Angeles", hàm của bạn sẽ trả về các chuyển đổi là 3/9/2014 3:00:00 AM11/2/2014 2:00:00 AM, nơi bạn có thể mong đợi 2:00 sáng cho cả hai.

  • Các múi giờ ở phía nam đường xích đạo sử dụng DST sẽ bắt đầu vào cuối năm và kết thúc vào đầu năm sau. Vì vậy, đôi khi các mục trong tuple có thể được đảo ngược từ những gì bạn mong đợi họ được.

  • Có khá nhiều múi giờ không sử dụng thời gian tiết kiệm ánh sáng ban ngày, vì vậy việc ném ngoại lệ không phải là ý tưởng hay nhất.

  • Có ít nhất hai múi giờ hiện có bốn lần chuyển tiếp trong một năm ("Africa/Casablanca""Africa/Cairo") - có dấu ngắt trong khoảng thời gian DST cho tháng Ramadan. Và đôi khi, có các chuyển đổi không liên quan đến DST, chẳng hạn như khi Samoa changed its standard offset in 2011, cho phép chuyển đổi ba trong một năm.

Xem xét tất cả điều này, có vẻ tốt hơn để trả về danh sách các điểm chuyển tiếp đơn, chứ không phải là một bộ các cặp chuyển tiếp.

Ngoài ra, đây là nhỏ, nhưng nó sẽ là hình thức tốt hơn để không ràng buộc các phương pháp để đồng hồ hệ thống ở tất cả. Năm có thể dễ dàng được thông qua bởi tham số. Sau đó, bạn có thể sử dụng phương pháp này cho các năm không hiện tại nếu cần thiết.

public IEnumerable<LocalDateTime> GetDaylightSavingTransitions(DateTimeZone timeZone, int year) 
{ 
    var yearStart = new LocalDateTime(year, 1, 1, 0, 0).InZoneLeniently(timeZone).ToInstant(); 
    var yearEnd = new LocalDateTime(year + 1, 1, 1, 0, 0).InZoneLeniently(timeZone).ToInstant(); 
    var intervals = timeZone.GetZoneIntervals(yearStart, yearEnd); 

    return intervals.Select(x => x.IsoLocalEnd).Where(x => x.Year == year); 
} 

Cũng lưu ý cuối cùng, điều quan trọng là để lọc chỉ các giá trị mà là trong năm nay vì các khoảng rất tốt có thể kéo dài sang năm sau, hoặc đi trên vô thời hạn.

+0

Đây có phải là cơ sở chính xác cho phương pháp đơn giản IsDaylightSavings (DateTimeZone timeZone, Instant tức thì) hoặc có cách nào tốt hơn không? – davidkomer

+0

Phương pháp của bạn làm gì? Tài liệu của Noda Time không dễ hiểu. Tôi không hiểu 'IsoLocalEnd' là gì và nó có thể được sử dụng như thế nào để có được thời gian chuyển tiếp DST. – Azimuth

+0

@Azimuth - Theo tài liệu, một 'ZoneInterval' *" đại diện cho một khoảng thời gian mà một Offset cụ thể áp dụng, "* và [IsoLocalEnd'] của nó (http://nodatime.org/1.3.x/api/ ? topic = html/P_NodaTime_TimeZones_ZoneInterval_IsoLocalEnd.htm) property * "trả về thời gian bắt đầu cục bộ của khoảng, như' LocalDateTime' trong lịch ISO. Điều này không bao gồm bất kỳ tiết kiệm ánh sáng ban ngày nào "*. Đây là khoảng thời gian nửa mở, do đó, điều này cho chúng ta thời gian địa phương mà quá trình chuyển đổi diễn ra. –

Các vấn đề liên quan