问题描述
这段代码:
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
...produces this result in my database: 2008-05-01 00:00:00.0000000 -04:00
我应该如何修改我的代码,以便在 testDateAndTime
中将时区偏移量从 -4:00
更改为 +00:00
?
How should I revise my code so that it changes the time zone offset from -4:00
to +00:00
in testDateAndTime
?
我也试过了:
public Task<DateTimeOffset> SetTimeZoneOffsetToZero(DateTimeOffset dateTimeOffSetObj)
{
TimeSpan zeroOffsetTimeSpan = new TimeSpan(0, 0, 0, 0, 0);
return dateTimeOffSetObj.ToOffset(zeroOffsetTimeSpan);
}
...但是那段代码什么也没做.
...but that code doesn't do anything.
我的最终目标只是有一个没有时间或时区偏移的日期.我确实不想将时间转换为另一个时区.(也就是说,我不想从 00:00:00.0000000
时间中减去 4 小时,并将设置的时间偏移量删除为 +00:00
.我 只是想将偏移量设置为+00:00
.)
My end goal is just to have a date without a time or a time zone offset. I do not want to convert the time to another time zone. (That is, I don't want to subtract 4 hours from the 00:00:00.0000000
time and remove set time offset to +00:00
. I just want to set the offset to +00:00
.)
这是我在其他地方遇到的另一种方法:
Here is another approach that I came across elsewhere:
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
.也就是说,改变both时间和时区偏移.但是,我的测试表明此代码 just 更改了时区偏移量,这正是我想要的.这样做有问题吗?
I was sure that SpecifyKind
would convert my DateTimeOffset
. That is, change both the time and the time zone offset. But, my test indicates that this code just changes the time zone offset, which is what I want. Is there a problem with doing it this way?
推荐答案
这个问题实际上和数据库没有任何关系.如果您在某处设置断点或记录输出,您应该能够看到在此代码之后不久添加的偏移量:
The issue doesn't have anything to do with the database actually. If you set a breakpoint or log the output somewhere, you should be able to see the offset being tacked on shortly after this code:
testDateAndTime = testDateAndTime.DateTime.Date;
让我们分解一下:
- 您从
2008-05-01T08:06:32+01:00
的 - 然后您调用了
.DateTime
,这导致2008-05-01T08:06:32
的DateTime
值与DateTimeKind.Unspecified
. - 然后您调用了
.Date
,这导致2008-05-01T00:00:00
的DateTime
值与DateTimeKind.Unspecified
. - 您将结果分配回
testDateAndTime
,它的类型为DateTimeOffset
.这会调用从DateTime
到DateTimeOffset
的隐式转换 - 应用 本地 时区.在您的情况下,您当地时区的此值的偏移量似乎是-04:00
,因此结果值是2008- 的
,如你所述.DateTimeOffset
05-01T00:00:00-04:00
DateTimeOffset
值开始- You started with a
DateTimeOffset
value of2008-05-01T08:06:32+01:00
- You then called
.DateTime
, which resulted in aDateTime
value of2008-05-01T08:06:32
withDateTimeKind.Unspecified
. - You then called
.Date
, which resulted in aDateTime
value of2008-05-01T00:00:00
withDateTimeKind.Unspecified
. - You assign the result back to
testDateAndTime
, which is of typeDateTimeOffset
. This invokes an implicit cast fromDateTime
toDateTimeOffset
- which applies the local time zone. In your case, it would appear the offset for this value in your local time zone is-04:00
, so the resulting value is aDateTimeOffset
of2008-05-01T00:00:00-04:00
, as you described.
你说:
最终目标只是有一个没有时间或时区偏移的日期.
End goal is just to have a date without time or time zone offset.
嗯,目前没有原生 C# 数据类型,它只是一个没有时间的日期. 的 System.Time 包中有一个纯 Date
类型corefxlab,但这还没有为典型的生产应用程序做好准备.Noda Time 库中有 LocalDate
,您现在可以使用,但您仍然必须使用在保存到数据库之前转换回本机类型.因此,与此同时,您能做的最好的事情是:
Well, there is currently no native C# data type that is just a date without a time. There is a pure Date
type in the System.Time package in corefxlab, but that's not quite ready for the typical production application. There's LocalDate
in the Noda Time library that you can use today, but you'd still have to convert back to a native type before saving to the database. So in the meantime, the best you can do is:
- 将您的 SQL Server 更改为在字段中使用
date
类型. - 在您的 .NET 代码中,使用时间为
00:00:00
和DateTimeKind.Unspecified
的DateTime
.您必须记住忽略时间部分(因为在某些时区确实存在没有当地午夜的日期). - 将您的
test
属性更改为DateTime
,而不是DateTimeOffset
.
- Change your SQL Server to use a
date
type in the field. - In your .NET code, use a
DateTime
with a time of00:00:00
andDateTimeKind.Unspecified
. You'll have to remember to ignore the time portion (as there are indeed dates without a local midnight in certain time zones). - Change your
test
prop to be aDateTime
, not aDateTimeOffset
.
一般来说,虽然 DateTimeOffset
适合大量场景(例如 timestamping 事件),但它不太适合仅日期值.
In general, while DateTimeOffset
fits a large number of scenarios (such as timestamping events), it doesn't fit well for date-only values.
我想要当前日期,偏移量为零.
I want the current date, with zero offset.
如果你真的想要这个作为 DateTimeOffset
,你会这样做:
If you really want this as a DateTimeOffset
, you'd do:
testDateAndTime = new DateTimeOffset(testDateAndTime.Date, TimeSpan.Zero);
但是,我建议不要这样做.通过这样做,您将获取原始值的 local 日期并断言它是 UTC.如果原始偏移量不是零,那将是错误的断言.以后肯定会导致其他错误,因为您实际上是在谈论与您创建的时间点不同的时间点(可能是不同的日期).
However, I advise against this. By doing so, you're taking the local date of the original value and asserting that it is in UTC. If the original offset is anything other than zero, that would be a false assertion. It is bound to lead to other errors later, as you're actually talking about a different point in time (with potentially a different date) than the one you created.
关于您在编辑中提出的附加问题 - 指定 DateTimeKind.Utc
会更改隐式转换的行为.它不使用本地时区,而是使用 UTC 时间,其偏移量始终为零.结果与我上面给出的更明确的形式相同.出于同样的原因,我仍然建议不要这样做.
Regarding the additional question asked in your edit - Specifying DateTimeKind.Utc
changes the behavior of the implicit cast. Instead of using the local time zone, it uses UTC time, which always has an offset of zero. The result is the same as the more explicit form I gave above. I still recommend against this, for the same reasons.
考虑以 2016-12-31T22:00:00-04:00
开头的示例.通过您的方法,您可以将 2016-12-31T00:00:00+00:00
保存到数据库中.然而,这是两个非常不同的时间点.标准化为 UTC 的第一个将是 2017-01-01T02:00:00+00:00
,而转换为另一个时区的第二个将是 2016-12-30T20:00:00-04:00
.注意转换中日期的变化.这可能不是您希望潜入应用程序的行为.
Consider an example of starting with 2016-12-31T22:00:00-04:00
. By your approach, you'd save into the database 2016-12-31T00:00:00+00:00
. However these are two very different points in time. The first one normalized to UTC would be 2017-01-01T02:00:00+00:00
, and the second one converted to the other time zone would be 2016-12-30T20:00:00-04:00
. Notice the change of dates in the conversion. This is probably not the behavior you'd want creeping into your application.
这篇关于从 DateTimeOffset 中删除时区偏移量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!