首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DateTimeOffset同日比较

DateTimeOffset同日比较
EN

Stack Overflow用户
提问于 2014-11-23 19:07:23
回答 5查看 6.1K关注 0票数 3

在下面的要求中,我遇到了有趣的问题:测试一个进程是否在同一天内运行,如果没有运行该进程。日期以DataTimeOffset形式存储。

我最初的做法是:

  1. 将两个值转换为UTC,因为这些日期可能是在不同的时区中创建的,并且有不同的偏移量。
  2. 查看每个值的日期值。这是在转换到UTC之后完成的,因为Date方法忽略了偏移量。

大多数情况下,这是可行的,但我遇到了一个情况,即逻辑将失败。如果其中一个值的时间接近上一天/第二天,那么当转换为UTC时,它将更改日期。如果其他值没有时间也转换为前一天/第二天,则日期比较失败。

因此,我得到了下面的逻辑来包含这个场景:

代码语言:javascript
复制
public static bool SameDate(DateTimeOffset first, DateTimeOffset second)
{
    bool returnValue = false;
    DateTime firstAdjusted = first.ToUniversalTime().Date;
    DateTime secondAdjusted = second.ToUniversalTime().Date;

    // If date is now a day ahead after conversion, than add/deduct a day to other date if that date hasn't advanced
    if (first.Date < firstAdjusted.Date && second.Date == secondAdjusted.Date)
        secondAdjusted = secondAdjusted.Date.AddDays(1);
    if (first.Date > firstAdjusted.Date && second.Date == secondAdjusted.Date)
        secondAdjusted = secondAdjusted.Date.AddDays(-1);

    if (second.Date < secondAdjusted.Date && first.Date == firstAdjusted.Date)
        firstAdjusted = firstAdjusted.Date.AddDays(1);
    if (second.Date > secondAdjusted.Date && first.Date == firstAdjusted.Date)
        firstAdjusted = firstAdjusted.Date.AddDays(-1);

    if (DateTime.Compare(firstAdjusted, secondAdjusted) == 0)
        returnValue = true;

    return returnValue;
}

以下是未能通过的单元测试:

代码语言:javascript
复制
 [TestMethod()]
 public void SameDateTest()
 {
 DateTimeOffset current = DateTimeOffset.Now;
 DateTimeOffset first = current;
 DateTimeOffset second = current;

 // 23 hours later, next day, with negative offset (EST) -- First rolls over
 first = new DateTimeOffset(2014, 1, 1, 19, 0, 0, new TimeSpan(-5, 0, 0));
 second = new DateTimeOffset(2014, 1, 2, 18, 0, 0, new TimeSpan(-5, 0, 0));
 Assert.IsFalse(Common.SameDate(first, second));

 // 23 hours earlier, next day, with postive offset -- First rollovers
 first = new DateTimeOffset(2014, 1, 1, 4, 0, 0, new TimeSpan(5, 0, 0));
 second = new DateTimeOffset(2014, 1, 2, 5, 0, 0, new TimeSpan(5, 0, 0));
 Assert.IsFalse(Common.SameDate(first, second));

 // 23 hours later, next day, with negative offset (EST) -- Second rolls over
 first = new DateTimeOffset(2014, 1, 2, 18, 0, 0, new TimeSpan(-5, 0, 0));
 second = new DateTimeOffset(2014, 1, 1, 19, 0, 0, new TimeSpan(-5, 0, 0));
 Assert.IsFalse(Common.SameDate(first, second));

 // 23 hours earlier, next day, with postive offset -- Second rolls over
 first = new DateTimeOffset(2014, 1, 2, 5, 0, 0, new TimeSpan(5, 0, 0));
 second = new DateTimeOffset(2014, 1, 1, 4, 0, 0, new TimeSpan(5, 0, 0));
 Assert.IsFalse(Common.SameDate(first, second));
}

我的直觉是,有一个更清洁的方法,比增加/减少的基础上的其他价值。有没有更好的方法?

主要标准:

  1. 调整这两个日期以具有相同的偏移量。
  2. 只有当第一天和第二天都发生在同一日历日,而不是在24小时内,才返回true。
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-12-01 19:25:57

根据两个日期的差异调整其中一个日期:

代码语言:javascript
复制
public static bool SameDate(DateTimeOffset first, DateTimeOffset second)
{
    bool returnValue = false;
    DateTime firstAdjusted = first.ToUniversalTime().Date;
    DateTime secondAdjusted = second.ToUniversalTime().Date;

    // calculate the total diference between the dates   
    int diff = first.Date.CompareTo(firstAdjusted) - second.Date.CompareTo(secondAdjusted);
    // the firstAdjusted date is corected for the difference in BOTH dates.
    firstAdjusted = firstAdjusted.AddDays(diff);

    if (DateTime.Compare(firstAdjusted, secondAdjusted) == 0)
        returnValue = true;

    return returnValue;
}

在这个函数中,我要指出,抵消时间永远不会超过24小时。一个日期和它的调整日期之间的差额不会是两天或两天以上。如果不是这样,那么您可以使用time span比较。

票数 4
EN

Stack Overflow用户

发布于 2014-11-25 23:58:11

您所描述的一般方法(转换为公共时区,然后比较日期部分)是合理的。这里的问题实际上是一个决定参照系的问题。你随意选择了UTC作为你的参照系。起初,光泽度并不重要,只要它们在同一时区进行比较,但是正如您已经发现的,这可以将它们置于一天边界的任何一边。

我认为你需要改进你的规格。问问自己,以下哪一个是你想要确定的。

  • 值是否发生在指定时区的同一日历日。
  • 值是否相隔不超过12小时(+/- 12小时是一个24小时的周期)。
  • 值是否相隔不超过24小时。

也可能是别的东西。已实现的定义(但被您拒绝)是“值是否发生在相同的UTC日历日”。

票数 3
EN

Stack Overflow用户

发布于 2014-12-01 23:10:52

首先,你需要澄清一些混乱的程序应该做什么。对于两个普通时区中的两个通用时间戳(两个没有特定限制的DateTimeOffset实例),不存在“日历日”这样的概念。每个时区都有自己的日历日。例如,我们可以有两个DateTimeOffset实例,名为firstsecond,它们有不同的偏移量。让我们可视化时间轴,并用DateTimeOffset实例引用的特定时间点( * )和相应时区中的日历日(即特定时区中0:00到23:59之间的间隔)使用|__|标记。看起来可能是这样的:

代码语言:javascript
复制
first:  ........|___________________*__|.......
second: ...|______*_______________|............

first的时区中,second事件发生在同一日历日(凌晨2点至3点之间)。在second的时区中,first事件发生在下一个日历日(凌晨1点到2点之间)。

因此,很明显,这个问题需要澄清,而且可能需要一些范围的限制。这些时区是真正的通用时区,还是属于同一地点的时区,仅在夏令时可能有所不同?既然如此,你为什么不直接忽略时区呢?例如,在2014年11月2日00:10到23:50之间,UTC偏移量发生了变化(EDT->ET),这两个瞬间之间的间隔超过24小时:new DateTimeOffset(2014, 11, 02, 00, 10, 00, new TimeSpan(-4, 0, 0)).Date == new DateTimeOffset(2014, 11, 02, 23, 50, 00, new TimeSpan(-5, 0, 0)).Date。基本上,这就是martijn试图做的事情,但方法非常复杂。当你试着

代码语言:javascript
复制
public static bool SameDateSimple(DateTimeOffset first, DateTimeOffset second)
{
    return first.Date == second.Date;
}

它将适用于所有上述单元测试。而且,这也是大多数人所称的“同一个日历日”,保证这两个实例指的是同一地点的时间。

或者,如果你真的在比较两个“随机”时区,你必须选择你的参考时区。它可能是UTC,正如你最初尝试的那样。或者,从人类的角度来看,使用第一个时区作为参考可能更合乎逻辑(您也可以选择第二个时区,它会给出不同的结果,但这两个变体“同样好”):

代码语言:javascript
复制
public static bool SameDateGeneral(DateTimeOffset first, DateTimeOffset second)
{
    DateTime secondAdjusted = second.ToOffset(first.Offset).Date;
    return first.Date == secondAdjusted.Date;
}

这对于上述一些测试不起作用,但对于两个随机时区来说,它的工作“正确”(在某种意义上)更为普遍:如果您尝试first = new DateTimeOffset(2014, 1, 2, 0, 30, 0, new TimeSpan(5, 0, 0)), second = new DateTimeOffset(2014, 1, 1, 23, 30, 0, new TimeSpan(4, 0, 0)),简单的SameDateSimple返回false (与martijn一样),尽管这两个实例引用的时间完全相同(都是2014-01-01 19:30:00Z)。SameDateGeneral在这里正确地返回true

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27093065

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档