如何将时间和olson时区转换为另一个olson时区的时间?

时间:2013-03-04 04:23:35

标签: c# datetime nodatime

我有一个输入:

  1. 时间(上午8:00)
  2. 奥尔森时区(America / New_York)
  3. 我需要将时间转换为另一个奥尔森时区(America / Los_Angeles)

    .net或nodatime进行转换的最佳方法是什么。我基本上在C#中寻找相当于这个方法的东西:

      var timeInDestinationTimeZone = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(CurrentSlot.Date, TimeZoneInfo.Local.Id,
                                                                                room.Location.TimeZone.TimeZoneName);
    

    但上面的.Net方法仅适用于Windows时区名称(我有Olson名称)

2 个答案:

答案 0 :(得分:4)

观察:

var tzdb = DateTimeZoneProviders.Tzdb;

var zone1 = tzdb["America/New_York"];
var ldt1 = new LocalDateTime(2013, 3, 4, 8, 0); // March 4th, 2013 - 8:00 AM
var zdt1 = zone1.AtLeniently(ldt1);

var zone2 = tzdb["America/Los_Angeles"];
var zdt2 = zdt1.ToInstant().InZone(zone2);
var ldt2 = zdt2.LocalDateTime;

请注意对AtLeniently的调用 - 这是因为您没有足够的信息来确定您正在谈论的那个时刻。例如,如果您在DST回退过渡当天凌晨1:30谈论,您将不知道您是在转换之前还是之后谈论。 AtLeniently会在之后做出的假设。如果您不想要这种行为,则必须提供一个偏移量,以便了解您正在谈论的当地时间。

实际的转换ToInstant完成,它正在获取您正在讨论的UTC时刻,然后InZone将其应用于目标区域。

答案 1 :(得分:3)

替代Matt的第二部分(非常好)答案:

// All of this part as before...
var tzdb = DateTimeZoneProviders.Tzdb;    
var zone1 = tzdb["America/New_York"];
var ldt1 = new LocalDateTime(2013, 3, 4, 8, 0); // March 4th, 2013 - 8:00 AM
var zdt1 = zone1.AtLeniently(ldt1);

var zone2 = tzdb["America/Los_Angeles"];

// This is just slightly simpler - using WithZone, which automatically retains
// the calendar of the existing ZonedDateTime, and avoids having to convert
// to Instant manually
var zdt2 = zdt1.WithZone(zone2);
var ldt2 = zdt2.LocalDateTime;