呵呵,我喜欢微软的做法,时间,然后尝试修复它以及您可以用非常有趣的方式来做看似明智的事情:) 有趣的可爱错误领域。
更新:首先要解决这个问题:IMO 出错的地方是您的日期格式不包含有关 UTC 零偏移量的时间信息,也不包含记录的偏移量信息
所以让我从最常见的错误开始,作为一个术语问题,.net(或者)UTC 是一个时刻的概念并不完全正确。它不是,实际上它是 ISO 8601 定义的一个符号,它可以而且应该以序列化形式传播并包含最大合规性的偏移量。 https://en.wikipedia.org/wiki/ISO_8601#Coordinated_Universal_Time_(UTC)
如果您关心,请通读https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-round-trip-date-and-time-values,如果您添加额外信息,请考虑它是否真的不是最实际的时间协调。
如果您想在雾蒙蒙的街道上散步,请尽情享受,您可以复制粘贴此单元测试并在监控本地人和调试输出窗口的同时逐步执行。
[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);
}
更新:我添加了定义的链接,所以就像有人立即指出的那样,它与通用时间协调中某个时刻的数据格式无关。
但是,如果完全诚实,英国格林威治经度的给定时间没有偏移“UTC”本身并不能协调任何东西,这是我们的意图,就像我们必须从名称中推测的那样。
所以例如我们在都柏林有一个云集群,例如为爱沙尼亚的客户提供服务。您需要一种格式的日期,该格式包含参考点的时间和数据的偏移量,以便在 IMO 前端有意义并可用,除非不断地相互转换是浪费资源。