问题描述
我从网络服务 2013-10-15T12:54:18 + 01:00
中获取以下字符串。这个日期是夏令时,我的.NET代码(我假设是Web服务代理)会自动添加一个小时。如果返回值随冬季DST而下降,则情况并非如此。返回的时间( 12:54:18
)是我要显示的时间,我不希望进行任何重新计算。
I'm getting a following string from a web service 2013-10-15T12:54:18+01:00
. This date is in the summer DST and my .NET code (web service proxy, I presume) automatically adds one hour to it. The same is not the case if the returned value falls withing the winter DST. The time returned (12:54:18
) is what I want to display, I don't want any sort of recalculation to be done.
我正在使用 TimeSpan DateTime.TimeOfDay
显示时间。
什么我该怎么做才能做到这一点?
What can I do to make it happen?
推荐答案
我正在尝试将您的问题和其他注释中的各个内容放在一起。到目前为止,这是我的分析:
I am trying to put the pieces together from your question and the additional comments. So far this is my analysis:
-
在网络上,您看到两个不同的日期和时间字符串:
On the wire you see two different date and time strings:
-
没有夏令时(冬季),字符串为
2013-12-30T12:54:18
具有夏时制(夏季),字符串为 2013-10-15T12:54:18 + 01:00
With daylight savings (summer) the string is 2013-10-15T12:54:18+01:00
这表明Web服务正在使用 GMT标准时间
This is a sign that the web service is using GMT Standard Time as the time zone.
您要从日期和时间字符串中提取GMT时间戳。
You want to extract the GMT timestamp from the date and time string.
但是,您和Web服务之间有一些未指定的 Web服务代理(我假设某种.NET框架?),并且在您的代码中,您只能访问 DateTime
,此外,您的代码是在中欧标准时间时区执行的,如果我们忽略了夏季和冬季,则基本上比格林尼治标准时间早一小时在短时间内过渡到
However, between you and the web service there is some unspecified web service proxy (I assume some kind of .NET framework?) and in your code you only have access to a DateTime
and furthermore your code is executing in the Central Europe Standard Time time zone which basically is one hour ahead of GMT both during summer and winter if we disregard the short time where there is a transition to and from daylight savings.
我希望到目前为止我是对的。
I hope I am correct so far.
您可以使用以下代码将传入的 DateTime
转换为GMT:
You can convert the incoming DateTime
to GMT using this code:
// Framework code creates the DateTime.
var sourceDateTime = DateTime.Parse("2013-10-15T12:54:18+01:00");
// Application code can further process the DateTime.
var destinationTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
var destinationDateTime = TimeZoneInfo.ConvertTime(sourceDateTime, destinationTimeZoneInfo);
此示例在夏令时给出了正确的答案。传入的日期和时间字符串包含偏移量,并且已正确解析为本地时区(CET)。 TimeZoneInfo.ConvertTime
假定源 DateTime
在本地时区,并且结果正确。
This example gives the correct answer during daylight savings. The incoming date and time string contains an offset and is correctly parsed into a local time zone (CET). The TimeZoneInfo.ConvertTime
assumes that the source DateTime
is in the local time zone and the result is correct.
但是,该代码在没有夏令时的冬季会失败:
However, the code fails during winter where there is no daylight savings:
var sourceDateTime = DateTime.Parse("2013-12-30T12:54:18");
请注意,日期和时间字符串不再包含时区偏移。偏移量为 +00:00
,但由于某种原因,字符串中缺少该偏移量。这意味着源 DateTime
被假定为位于本地时区(CET),而不是从实际时区(GMT)转换而来。 如果我的分析正确,这就是问题的根源。
Notice that the date and time string no longer contains a time zone offset. The offset is +00:00
but for some reason it is missing from the string. This means that the source DateTime
is assumed to be in the local time zone (CET) and not converted from the actual time zone (GMT). This is the source of your problem if my analysis is correct.
另一种解释方式:
| Server (GMT) | Framework (CET) | My code
-------+---------------+---------------------------+----------------------------
Summer | +01:00 suffix | GMT -> CET adds 1 hour | CET -> GMT subtracts 1 hour
-------+---------------+---------------------------+----------------------------
Winter | No suffix | Assumed to be CET | CET -> GMT subtracts 1 hour
没有容易解决的问题。如果您可以说服Web服务提供正确的偏移量,即使它是 +00:00
,我的上述代码在夏季和冬季都可以使用。更好的是,仅使用UTC,并且仅在最终用户参与时才转换为本地时间。但是我想您无法控制Web服务吗?
There is no easy fix for this problem. If you could persuade the web service to provide the correct offset even when it is +00:00
my code above would work both summer and winter. Even better, only use UTC and only convert to a local time when the end-user gets involved. But I guess that you have no control over the web service?
一种选择是在与服务器相同的时区(例如GMT)中执行代码。然后,您应该可以直接使用时间戳,而无需进行任何转换。
One option would be to execute your code in the same time zone as the server (e.g. GMT). Then you should be able to use the timestamp directly without any conversion.
另一个更丑陋的选择是确定Web服务是否在夏令时之外,然后相应地调整时间。 :
Another more ugly option is to determine if the web service is outside daylight savings and then adjust the time accordingly:
var destinationTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
if (!destinationTimeZoneInfo.IsDaylightSavingTime(sourceDateTime)) {
var sourceDateTimeOffset = new DateTimeOffset(sourceDateTime, destinationTimeZoneInfo.BaseUtcOffset);
sourceDateTime = sourceDateTimeOffset.UtcDateTime;
}
var destinationDateTime = TimeZoneInfo.ConvertTime(sourceDateTime, destinationTimeZoneInfo);
我试图使代码尽可能通用,但实际上只是在解决问题缺少 +00:00
的情况,在这种情况下, destinationTimeZoneInfo.BaseUtcOffset
恰好为0,因此对于
I have tried to keep the code as general as possible but actually it is only trying to fix the situation where +00:00
is missing and in that case destinationTimeZoneInfo.BaseUtcOffset
is precisely 0 so it might be slightly overkill to do it like this.
更重要的是,我不确定在夏令时过渡期间这段代码是否能提供正确的结果。即使我相信GMT和CET在同一日期进行转换,CET仍比GMT提前一小时。您确实必须创建一些单元测试以确保获得所需的结果。
More importantly, I am not sure that this code provides the correct results during the time when there is a daylight savings transition. Even though I believe that GMT and CET transitions at the same date CET is still one hour ahead of GMT. You really have to create some unit tests to make sure you get the desired result.
这篇关于.net将夏季DST增加一小时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!