2014-11-01 43 views
1

我正在致力於writing a managed wrapper around Massachusetts Bay Transportation Authority (MBTA) Realtime API。他們有一個返回服務器時間的API,它是unix時間戳(epoch)。在這我實現它的圖書館是PCL Profile 78這意味着我已經限制了BCL的時區支持,所以我採取使用Nodatime使用Nodatime將時代戳記轉換爲東方時間的優雅方法

我試圖從服務器返回到美國東部時間時間是America/New_YorkDateTime轉換對象和逆向的方式。 My current code is very dirty

public static class TimeUtils 
{ 
    static readonly DateTimeZone mbtaTimeZone = DateTimeZoneProviders.Tzdb["America/New_York"]; 
    static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 

    public static DateTime GetMbtaDateTime (long unixTimestamp) 
    { 
     var mbtaEpochTime = epoch.AddSeconds (unixTimestamp); 
     var instant = Instant.FromUtc (mbtaEpochTime.Year, mbtaEpochTime.Month, 
      mbtaEpochTime.Day, mbtaEpochTime.Hour, mbtaEpochTime.Minute, mbtaEpochTime.Second); 
     var nodaTime = instant.InZone (mbtaTimeZone); 
     return nodaTime.ToDateTimeUnspecified(); 
    } 

    public static long MbtaDateTimeToUnixTimestamp (DateTime time) 
    { 
     TimeSpan secondsSinceEpochMbtaTz = time - epoch; 
     var instant = Instant.FromUtc (time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second); 
     var mbtaTzSpan = mbtaTimeZone.GetUtcOffset (instant).ToTimeSpan(); 
     var epochDiff = secondsSinceEpochMbtaTz - mbtaTzSpan; 
     return (long)epochDiff.TotalSeconds; 
    } 
} 

是否有另一種簡單的寫法。我希望Nodatime應該支持將紀元時間轉換爲America/New_York DateTime和America/New_York DateTime到紀元時間。我的方法是MbtaDateTimeToUnixTimestamp一個殘酷的黑客

+1

你真的需要使用'DateTime'嗎?當您在整個代碼中使用時,Noda Time的效果最佳。 – 2014-11-01 18:47:44

回答

6

首先,在註釋中提到的那樣,這將是最好的整個代碼中使用的野田時間類型 - 只能求助於DateTime當你真的來。這應該導致整個代碼更清晰。

轉換Unix時間戳到Instant是很容易的:

Instant instant = Instant.FromSecondsSinceUnixEpoch(seconds); 

然後,您可以轉換成ZonedDateTime按你目前的代碼......並且使用ToDateTimeUnspecified是好的,如果你真的需要使用DateTime

對於相反的情況,您的當前代碼對我來說很難理解 - 您假設DateTime是一個UTC值,這很有效。這與您以後使用時區不一致。我懷疑你想將輸入轉換爲LocalDateTime,然後應用時區。例如:

public static long MbtaDateTimeToUnixTimestamp(DateTime time) 
{ 
    var local = LocalDateTime.FromDateTime(time); 
    var zoned = local.InZoneStrictly(mbtaTimeZone); 
    var instant = zoned.ToInstant(); 
    return instant.Ticks/NodaConstants.TicksPerSecond; 
} 

請注意撥打InZoneStrictly。如果您通過本地時間不存在存在兩次 - 這兩種情況都是由於DST轉換導致的,這將引發異常。這很可能是而不是是你想要的 - 你真的需要考慮你想在這些情況下發生什麼,或者儘量避免它們可行。有關更多詳細信息和選項,請參閱time zones section of the documentation

相關問題