简体   繁体   English

检查日期(日期时间)是否为未知区域的夏令时 - c#

[英]Check a date (datetime) if it is Daylight Saving Time with unknown region - c#

With what I understood from other questions I've used below code for checking a date if it is Daylight saving time and altering as required.根据我从其他问题中了解到的情况,我使用下面的代码来检查日期是否是夏令时并根据需要进行更改。 I do not know which region would the application be used hence I am using Utc.我不知道应用程序将使用哪个区域,因此我使用的是 Utc。 However it is not working as expected.但是它没有按预期工作。

DateTime dateValWithOffset = dateVal;
TimeZoneInfo timeZoneInfo = TimeZoneInfo.Utc;

if(timeZoneInfo.IsDaylightSavingTime(dateValWithOffset))
{
 dateValWithOffset = dateValWithOffset.AddMinutes(60);
}

Example: for sample date (06-JUL-21 06.16.34.547000000 AM) above code should be showing dateValWithOffset as 07/06/2021 02:16:34.547 AM but it returns 07/06/2021 01:16:34.547 AM .示例:对于示例日期 (06-JUL-21 06.16.34.547000000 AM) ,上面的代码应将 dateValWithOffset 显示为07/06/2021 02:16:34.547 AM但它返回07/06/2021 01:16:34.547 AM If someone can point out where am I going wrong please.如果有人能指出我哪里错了,请。

As jason.kaisersmith said in comments, "UTC is universal, so there is no daylight saving."正如jason.kaisersmith在评论中所说,“UTC 是通用的,所以没有夏令时。”

To elaborate, UTC does not have any daylight saving time.详细地说,UTC 没有任何夏令时。 Instead, daylight saving time is observed differently at each time zone across the world.相反,世界各地的每个时区都以不同的方式观察夏令时。 Some time zones don't use it at all.有些时区根本不使用它。 Some time zones start and stop DST at different dates or times than other time zones.某些时区在与其他时区不同的日期或时间开始和停止 DST。 There's even one time zone that shifts for DST by 30 minutes instead of the usual 1 hour.甚至有一个时区将 DST 转换 30 分钟,而不是通常的 1 小时。 Without a time zone reference, the concept of DST is meaningless.如果没有时区参考,DST 的概念就毫无意义。

For clarity and reference, here's an overview of anticipated DST dates for 2022 by country , and a detailed list of dates and times for the first half and second half of 2022.为清楚起见和参考,这里是按国家/地区划分的 2022 年预计 DST 日期的概述,以及 2022 年上半年下半年的日期和时间的详细列表。

Datetime values should always be in UTC. Datetime值应始终采用 UTC。 To format a datetime in the machine or user's local timezone, you should convert to a DateTimeOffset .要在机器或用户的本地时区中格式化日期时间,您应该转换为DateTimeOffset Knowing the local time and knowing if that time is in daylight saving time are two different things.知道当地时间和知道那个时间是否在夏令时是两件不同的事情。

// machine local
var timeZoneInfo = TimeZoneInfo.Local;
// or by name
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(name);
var localTime = new DateTimeOffset(dateVal, timeZoneInfo.GetUtcOffset(dateVal));
var isDst = timeZoneInfo.IsDaylightSavingTime(localTime)

IMHO DateTime is a terrible type, designed before the age of cloud computing.恕我直言DateTime是一种可怕的类型,设计于云计算时代之前。 All DateTimeKind values other than Utc encourage programmers to continue to handle dates incorrectly and should be deprecated.Utc之外的所有DateTimeKind值都鼓励程序员继续错误地处理日期,应弃用。

Hehe, i love how Microsoft did, time, then tried to fix it and the very interesting ways you can f'it up doing seemingly sensible things:) amusing field of cute bugs.呵呵,我喜欢微软的做法,时间,然后尝试修复它以及你可以用非常有趣的方式来完成看似明智的事情:) 有趣的可爱错误领域。

update: To address the question first: Where you went wrong IMO is that your date format doesn't carry information about what the time was at UTC Zero offset, nor at what offset it is being recorded更新:首先解决这个问题:IMO 出错的地方是您的日期格式不包含有关 UTC 零偏移量的时间信息,也不包含记录的偏移量信息

So let me start out with the most common mistake which as a terminology matter isn't entirely well put with .net (either) the notion of UTC being a moment in time.因此,让我从最常见的错误开始,作为术语问题,.net(或者)UTC 是一个时刻的概念并不完全正确。 It's not, actually it is a notation as defined by ISO 8601 which can and should travel in serialized form and contain the offset for maximum compliance.它不是,实际上它是 ISO 8601 定义的一个符号,它可以而且应该以序列化的形式传播,并包含最大合规性的偏移量。 https://en.wikipedia.org/wiki/ISO_8601#Coordinated_Universal_Time_(UTC) https://en.wikipedia.org/wiki/ISO_8601#Coordinated_Universal_Time_(UTC)

Read through https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-round-trip-date-and-time-values if You care and consider if it isn't really most actually time coordinated if you add the extra info.如果您关心并考虑它是否不是真的, 请通读 https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-round-trip-date-and-time-values如果您添加额外的信息,最实际的时间协调。

Indulge me if you will in a walk down foggy street, You can copy paste this unit test and step through while monitoring your locals and your debug output windows.如果您想走在雾蒙蒙的街道上,请放纵我,您可以复制粘贴此单元测试并在监视本地人和调试 output windows 的同时逐步完成。

[TestMethod]
public void DateJugglingTest()
{
    var now = DateTime.Now; // local time, though on a server in the cloud, practially useless
    Debug.WriteLine(now.ToString("O"));            
    Debug.WriteLine(now.Kind.ToString());

    var utcZulu = DateTime.SpecifyKind(now, DateTimeKind.Utc); //now is not utc (zero) but intending it so will change the kind
    Debug.WriteLine(utcZulu.ToString("O"));
    Debug.WriteLine(utcZulu.Kind.ToString());
    Debug.WriteLine(utcZulu.ToLocalTime().ToString("O")); //local time at point of execution, notice we're an hour in the future, very common mistake

    var dateTimeOffset = new DateTimeOffset(now);//much more relevant datetime type in C# in a global village time period
    Debug.WriteLine(dateTimeOffset.DateTime.ToString("O"));
    Debug.WriteLine(dateTimeOffset.UtcDateTime.ToString("O"));

    dateTimeOffset = new DateTimeOffset(now, new TimeSpan(1,0,0));
    Debug.WriteLine(dateTimeOffset.DateTime.ToString("O"));
    Debug.WriteLine(dateTimeOffset.UtcDateTime.ToString("O"));
    Debug.WriteLine(dateTimeOffset.ToString("O"));

    var tzi = TimeZoneInfo.FindSystemTimeZoneById("Romance Standard Time");
    Debug.WriteLine(tzi.GetUtcOffset(utcZulu)); //another common pitfall because method is oblivious to datatime.kind
    Debug.WriteLine(tzi.GetUtcOffset(now));

    string utcFORMATstring = "2021-12-17T11:36:20.1234567+01:00"; //This is Universally Coordinated Time format a.k.a. UTC actually
    dateTimeOffset = DateTimeOffset.Parse(utcFORMATstring);
    Debug.WriteLine(tzi.GetUtcOffset(dateTimeOffset.DateTime));  //but this method still doesn't do right
    Debug.WriteLine(tzi.GetUtcOffset(dateTimeOffset.UtcDateTime)); //no matter which you choose

    Debug.WriteLine(dateTimeOffset.DateTime.ToUniversalTime().ToString("O")); //this one gets the right result
    Debug.WriteLine(dateTimeOffset.UtcDateTime.ToUniversalTime().ToString("O"));
    

    utcFORMATstring = "2021-12-17T11:36:20.1234567+00:00"; //equivalent to ...567Z
    dateTimeOffset = DateTimeOffset.Parse(utcFORMATstring);
    Debug.WriteLine(tzi.IsDaylightSavingTime(dateTimeOffset.DateTime)); //interesting feature to see if a given moment will be daylight saving in the actual timezone

    //Example
    var whenItWasAtZeroOffsetZuluTimeBecauseStoredAsRegularDateSomewhere = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc);
    var whenItWasSerializedAsIs = whenItWasAtZeroOffsetZuluTimeBecauseStoredAsRegularDateSomewhere.ToString("O");
    Debug.WriteLine(whenItWasSerializedAsIs);

    var whenItWasToTheSystem = whenItWasAtZeroOffsetZuluTimeBecauseStoredAsRegularDateSomewhere; //for the sake of imagined backward compatibility somewhere
    DateTime whenToDisplay;
    //If having to be manual because that is all you have            
    whenToDisplay = DateTime.SpecifyKind(whenItWasToTheSystem.Add(tzi.GetUtcOffset(whenItWasToTheSystem)), DateTimeKind.Local);
    Debug.WriteLine(whenToDisplay.ToString("O")); //And this is just because somebody at Microsoft hate the world :)) notice date is completely correctly configured but is way off

    //The way your api's should really send dates around, as strings carrying the offset
    dateTimeOffset = new DateTimeOffset(whenToDisplay, tzi.GetUtcOffset(whenItWasToTheSystem));
    var correctAtAnywhereInCloudTopology = dateTimeOffset.ToString("O"); //This is totally UTC as defined in ISO 8601
    Debug.WriteLine(correctAtAnywhereInCloudTopology);
    Assert.IsTrue(true);
}

Updated: I added the link to definition, so like somebody immediately pointed out, it doesn't relate to the formatting of data at what time a moment in the universally time coordinated is.更新:我添加了定义的链接,所以就像有人立即指出的那样,它与通用时间协调中某个时刻的数据格式无关。 However if being totally honest, what the time was at a given time in longitude Greenwich, UK without offset to the "UTC" doesn't coordinate in itself anything, which was the intend, like we have to presume from the name.但是,如果完全诚实,英国格林威治经度的给定时间在没有偏移“UTC”的情况下本身并不能协调任何东西,这就是我们的意图,就像我们必须从名称中推测的那样。 So eg we have a cloud cluster in Dublin, serving customers in Estonia for instance.例如,我们在都柏林有一个云集群,为爱沙尼亚的客户提供服务。 You need dates in a format which carries the time at reference point AND the offset for data to make sense and be usable in the frontends, IMO, unless constantly having to convert to and from which is a waste of resources.您需要一种格式的日期,该格式包含参考点的时间和数据的偏移量,以便在 IMO 前端有意义并可以使用,除非不断地相互转换是浪费资源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM