Noda Time - 从DateTime和TimeZoneId创建ZonedDateTime

vic*_*tor 1 c# datetime nodatime

假设我有以下日期,时间和时区:2016-10-15, 1:00:00, America/Toronto.

如何创建ZonedDateTime表示指定区域中确切日期和时间的?

基本上我需要一个ZonedDateTime对象来表示确切时区中的确切日期和时间.

如果跳过时间,我想在新时间添加小时标记.例:

如果00:00被跳到1:00,并且我试图在区域中获得00:30的时间,我希望结果是1:30,而不是1:00,这是间隔的第一次.

如果00:00被跳到1:45,并且我试图在区域中获得时间00:20,我希望结果为2:05.

如果时间不明确,即发生两次,我想要早期映射.

Jon*_*eet 5

你所描述的正是LocalDateTime.InZoneLenientlyNoda Time 2.0中的行为.(感谢Matt Johnson的改变 :)但是,由于这仍然是alpha,这里是1.3.2的解决方案.基本上,你只需要一个合适的ZoneLocalMappingResolver,你可以使用它构建Resolvers.这是一个完整的例子.

using NodaTime.TimeZones;
using NodaTime.Text;

class Program
{
    static void Main(string[] args)
    {
        // Paris went forward from UTC+1 to UTC+2
        // at 2am local time on March 29th 2015, and back
        // from UTC+2 to UTC+1 at 3am local time on October 25th 2015.
        var zone = DateTimeZoneProviders.Tzdb["Europe/Paris"];

        ResolveLocal(new LocalDateTime(2015, 3, 29, 2, 30, 0), zone);
        ResolveLocal(new LocalDateTime(2015, 6, 19, 2, 30, 0), zone);
        ResolveLocal(new LocalDateTime(2015, 10, 25, 2, 30, 0), zone);
    }

    static void ResolveLocal(LocalDateTime input, DateTimeZone zone)
    {
        // This can be cached in a static field; it's thread-safe.
        var resolver = Resolvers.CreateMappingResolver(
            Resolvers.ReturnEarlier, ShiftForward);

        var result = input.InZone(zone, resolver);
        Console.WriteLine("{0} => {1}", input, result);
    }

    static ZonedDateTime ShiftForward(
        LocalDateTime local,
        DateTimeZone zone,
        ZoneInterval intervalBefore,
        ZoneInterval intervalAfter)
    {
        var instant = new OffsetDateTime(local, intervalBefore.WallOffset)
            .WithOffset(intervalAfter.WallOffset)
            .ToInstant();
        return new ZonedDateTime(instant, zone);
    }            
}
Run Code Online (Sandbox Code Playgroud)

输出:

29/03/2015 02:30:00 => 2015-03-29T03:30:00 Europe/Paris (+02)
19/06/2015 02:30:00 => 2015-06-19T02:30:00 Europe/Paris (+02)
25/10/2015 02:30:00 => 2015-10-25T02:30:00 Europe/Paris (+02)
Run Code Online (Sandbox Code Playgroud)