从DateTimeOffset中删除时区偏移量

时间:2016-05-16 15:47:37

标签: c# timezone datetimeoffset

        DateTimeOffset testDateAndTime = new DateTimeOffset(2008, 5, 1, 8, 6, 32, new TimeSpan(1, 0, 0));

        //CLEAN TIME AND DATE 
        testDateAndTime = testDateAndTime.DateTime.Date; 

        var datesTableEntry = db.DatesTable.First(dt => dt.Id == someTestId);
        datesTableEntry.test= testDateAndTime;

        db.SaveChangesAsync(); 

结果数据库:2008-05-01 00:00:00.0000000 -04:00

如何将-4:00变为+00:00(在保存之前从代码中转移)?

我试过了:

    public Task<DateTimeOffset> SetTimeZoneOffsetToZero(DateTimeOffset dateTimeOffSetObj)
    {
        TimeSpan zeroOffsetTimeSpan = new TimeSpan(0, 0, 0, 0, 0);
        return dateTimeOffSetObj.ToOffset(zeroOffsetTimeSpan);
    }

它没有做任何事情。

最终目标只是拥有一个没有时间或时区偏移的日期。我不想将时间转换为另一个时区(即我不希望它从00:00:00.0000000时间减去4小时并将设置时间偏移移除到+00:00,我只是想让它设置偏移量到+00:00)。我想要当前日期,零偏移。

编辑:

以下是其他地方的建议:

    DateTimeOffset testDateAndTime = new DateTimeOffset(2008, 5, 1, 8, 6, 32, new TimeSpan(1, 0, 0));
    testDateAndTime = testDateAndTime.DateTime.Date; //Zero out time portion
    testDateAndTime = DateTime.SpecifyKind(testDateAndTime.Date, DateTimeKind.Utc); //"Zero out" offset portion

我确信SpecifyKind会转换我的dateTimeOffset,例如改变时间和时区偏移,但在测试时,它似乎只是改变时区偏移,这就是我想要的。这样做是否有问题?

1 个答案:

答案 0 :(得分:13)

该问题实际上与数据库没有任何关系。如果您设置断点或在某处记录输出,您应该能够看到在此代码后不久加上的偏移:

testDateAndTime = testDateAndTime.DateTime.Date;

让我们打破这个:

  • 您的DateTimeOffset值为2008-05-01T08:06:32+01:00
  • 然后,您致电.DateTimeDateTime的{​​{1}}值为2008-05-01T08:06:32
  • 然后,您致电DateTimeKind.Unspecified.Date的{​​{1}}值为DateTime
  • 您将结果分配回2008-05-01T00:00:00,其类型为DateTimeKind.Unspecified。这会调用从testDateAndTimeDateTimeOffset的隐式广告 - ,它会应用本地时区。在您的情况下,您看到本地时区中此值的偏移量为DateTime,因此结果值为DateTimeOffset -04:00,如您所述。

你说:

  

最终目标只是拥有一个没有时间或时区偏移的日期。

嗯,目前没有本地C#数据类型,只是一个没有时间的日期。 corefxlab中的 System.Time 包中有一个纯DateTimeOffset类型,但这对于典型的生产应用程序还没有完全准备好。您今天可以使用Noda Time库中的2008-05-01T00:00:00-04:00,但在保存到数据库之前,您仍需要转换回本机类型。所以在此期间,你能做的最好的事情是:

  • 将SQL Server更改为在字段中使用Date类型。
  • 在.NET代码中,使用时间为LocalDatedate的{​​{1}}。你必须记住忽略时间部分(因为在某些时区确实没有当地午夜的日期)。
  • 将您的DateTime道具改为00:00:00,而不是DateTimeKind.Unspecified

通常,虽然test适合大量场景(例如 timestamping 事件),但它不适合仅限日期的值。

  

我想要当前日期,零偏移。

如果确实希望将其作为DateTime,您可以这样做:

DateTimeOffset

但是,我建议不要这样做。通过这样做,您将获取原始值的本地日期并声明它是UTC。如果原始偏移量不是零,那么这将是一个错误的断言。它之后肯定会导致其他错误,因为您实际上是在讨论与您创建的不同时间点(可能是不同的日期)。

关于编辑中提出的其他问题 - 指定DateTimeOffset会更改隐式演员的行为。它不使用本地时区,而是使用UTC时间,它始终具有零偏移。结果与我上面给出的更明确的形式相同。出于同样的原因,我仍然建议不要这样做。

考虑以DateTimeOffset开头的示例。按照您的方法,您将保存到数据库testDateAndTime = new DateTimeOffset(testDateAndTime.Date, TimeSpan.Zero); 中。然而,这是两个非常不同的时间点。标准化为UTC的第一个将是DateTimeKind.Utc,而转换为另一个时区的第二个将是2016-12-31T22:00:00-04:00。请注意转换中日期的更改。这可能不是您想要进入应用程序的行为。