2014-11-01 37 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

相关问题