Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用NodaTime比较两种不同的时区时间跨度_C#_Datetime_Timezone_Nodatime - Fatal编程技术网

C# 使用NodaTime比较两种不同的时区时间跨度

C# 使用NodaTime比较两种不同的时区时间跨度,c#,datetime,timezone,nodatime,C#,Datetime,Timezone,Nodatime,我有一个要求,我有点困惑。我开始使用NodaTime,我认为这是最好的方法 我有两个用户,User1和User2都在两个不同的时区。他们可以在下午2点到5点之间会面,例如在当地时区。如果User2与User1的偏移量为+2小时,则重叠时间仅为1小时。我想得到的是,User1和User2的实际时间重叠的小时数是一个额外的值 到目前为止,我只知道: var user1TimeZone = DateTimeZoneProviders.Tzdb.GetZoneOrNull(user1timezone);

我有一个要求,我有点困惑。我开始使用NodaTime,我认为这是最好的方法

我有两个用户,User1和User2都在两个不同的时区。他们可以在下午2点到5点之间会面,例如在当地时区。如果User2与User1的偏移量为+2小时,则重叠时间仅为1小时。我想得到的是,User1和User2的实际时间重叠的小时数是一个额外的值

到目前为止,我只知道:

var user1TimeZone = DateTimeZoneProviders.Tzdb.GetZoneOrNull(user1timezone);
var user2TimeZone = DateTimeZoneProviders.Tzdb.GetZoneOrNull(user2timeZone);
我该如何着手解决这个问题


谢谢,

如果您有这样做的服务器,您必须发送UTC,然后进行比较。当您在客户端获得时间时,您必须将其转换为本地时间。这意味着,当第一个用户想要安排一次会议时,他会将自己的时间发送到服务器,然后当第二个用户得到这个时间时,他会将其转换为自己的本地时间

// First user sends UTC.
DateTime firstUserTime = DateTime.UtcNow;

// Second user gets time in his time zone.
DateTime secondUserTime = firstUserTime.ToLocalTime();

如果您有这样做的服务器,则必须发送UTC,然后进行比较。当您在客户端获得时间时,您必须将其转换为本地时间。这意味着,当第一个用户想要安排一次会议时,他会将自己的时间发送到服务器,然后当第二个用户得到这个时间时,他会将其转换为自己的本地时间

// First user sends UTC.
DateTime firstUserTime = DateTime.UtcNow;

// Second user gets time in his time zone.
DateTime secondUserTime = firstUserTime.ToLocalTime();

首先,要意识到它可能每天都在变化:不要将时区视为固定的偏移量

其次,请注意,为每个开始/结束指定的本地时间甚至可能不会发生,或者可能发生两次。确定您希望如何处理不明确和跳过的时间

对于任何特定的一天,我都会通过ZoneDateTime将用户的开始/结束时间转换为即时时间,然后您可以找到重叠部分。这确实假设任何重叠发生在同一天,但是。。。事实并非如此。我马上要开一个会议,其中一位与会者在新西兰——这里是3月14日,那里是3月15日。考虑到这一点是相当棘手的

下面是相对简单的案例的代码:

using NodaTime;
using System;

class Test
{
    static void Main()
    {
        // My availability: 4pm-7pm in London        
        var jon = new Availability(
            DateTimeZoneProviders.Tzdb["Europe/London"],
            new LocalTime(16, 0, 0),
            new LocalTime(19, 0, 0));
        // My friend Richard's availability: 12pm-4pm in New York
        var richard = new Availability(
            DateTimeZoneProviders.Tzdb["America/New_York"],
            new LocalTime(12, 0, 0),
            new LocalTime(16, 0, 0));

        // Let's look through all of March 2017...
        var startDate = new LocalDate(2017, 3, 1);
        var endDate = new LocalDate(2017, 4, 1);
        for (LocalDate date = startDate; date < endDate; date = date.PlusDays(1))
        {
            var overlap = GetAvailableOverlap(date, jon, richard);
            Console.WriteLine($"{date:yyyy-MM-dd}: {overlap:HH:mm}");
        }
    }

    static Duration GetAvailableOverlap(
        LocalDate date,
        Availability avail1,
        Availability avail2)
    {
        // TODO: Check that the rules of InZoneLeniently are what you want.
        // Be careful, as you could end up with an end before a start...
        var start1 = (date + avail1.Start).InZoneLeniently(avail1.Zone);
        var end1 = (date + avail1.End).InZoneLeniently(avail1.Zone);

        var start2 = (date + avail2.Start).InZoneLeniently(avail2.Zone);
        var end2 = (date + avail2.End).InZoneLeniently(avail2.Zone);

        var latestStart = Instant.Max(start1.ToInstant(), start2.ToInstant());
        var earliestEnd = Instant.Min(end1.ToInstant(), end2.ToInstant());

        // Never return a negative duration... return zero of there's no overlap.
        // Noda Time should have Duration.Max really...
        var overlap = earliestEnd - latestStart;
        return overlap < Duration.Zero ? Duration.Zero : overlap;
    }
}

public sealed class Availability
{
    public DateTimeZone Zone { get; }
    public LocalTime Start { get; }
    public LocalTime End { get; }

    public Availability(DateTimeZone zone, LocalTime start, LocalTime end)
    {
        Zone = zone;
        Start = start;
        End = end;
    }
}

首先,要意识到它可能每天都在变化:不要将时区视为固定的偏移量

其次,请注意,为每个开始/结束指定的本地时间甚至可能不会发生,或者可能发生两次。确定您希望如何处理不明确和跳过的时间

对于任何特定的一天,我都会通过ZoneDateTime将用户的开始/结束时间转换为即时时间,然后您可以找到重叠部分。这确实假设任何重叠发生在同一天,但是。。。事实并非如此。我马上要开一个会议,其中一位与会者在新西兰——这里是3月14日,那里是3月15日。考虑到这一点是相当棘手的

下面是相对简单的案例的代码:

using NodaTime;
using System;

class Test
{
    static void Main()
    {
        // My availability: 4pm-7pm in London        
        var jon = new Availability(
            DateTimeZoneProviders.Tzdb["Europe/London"],
            new LocalTime(16, 0, 0),
            new LocalTime(19, 0, 0));
        // My friend Richard's availability: 12pm-4pm in New York
        var richard = new Availability(
            DateTimeZoneProviders.Tzdb["America/New_York"],
            new LocalTime(12, 0, 0),
            new LocalTime(16, 0, 0));

        // Let's look through all of March 2017...
        var startDate = new LocalDate(2017, 3, 1);
        var endDate = new LocalDate(2017, 4, 1);
        for (LocalDate date = startDate; date < endDate; date = date.PlusDays(1))
        {
            var overlap = GetAvailableOverlap(date, jon, richard);
            Console.WriteLine($"{date:yyyy-MM-dd}: {overlap:HH:mm}");
        }
    }

    static Duration GetAvailableOverlap(
        LocalDate date,
        Availability avail1,
        Availability avail2)
    {
        // TODO: Check that the rules of InZoneLeniently are what you want.
        // Be careful, as you could end up with an end before a start...
        var start1 = (date + avail1.Start).InZoneLeniently(avail1.Zone);
        var end1 = (date + avail1.End).InZoneLeniently(avail1.Zone);

        var start2 = (date + avail2.Start).InZoneLeniently(avail2.Zone);
        var end2 = (date + avail2.End).InZoneLeniently(avail2.Zone);

        var latestStart = Instant.Max(start1.ToInstant(), start2.ToInstant());
        var earliestEnd = Instant.Min(end1.ToInstant(), end2.ToInstant());

        // Never return a negative duration... return zero of there's no overlap.
        // Noda Time should have Duration.Max really...
        var overlap = earliestEnd - latestStart;
        return overlap < Duration.Zero ? Duration.Zero : overlap;
    }
}

public sealed class Availability
{
    public DateTimeZone Zone { get; }
    public LocalTime Start { get; }
    public LocalTime End { get; }

    public Availability(DateTimeZone zone, LocalTime start, LocalTime end)
    {
        Zone = zone;
        Start = start;
        End = end;
    }
}

先将两者转换为UTC如何?然后,您可以根据需要将结果转换回UTC。先将两者转换为UTC如何?然后你可以根据需要将结果转换回来。太好了。非常感谢。这是一个很好的开始。太好了。非常感谢。这是一个很好的起点。