你需要了解的有关.NET日期时间的必要信息
引言
? ?DateTime數(shù)據(jù)類型是一個復雜的問題,復雜到足以讓你在編寫【將日期從Web服務器返回到瀏覽器】簡單代碼時感到困惑。
ASP.NET MVC 5和 Web API 2/ASP.NETCore 以不同方式序列化日期,這可能會給在一個Web應用程序中同時使用這兩個序列化的開發(fā)人員帶來更多混淆。
本文會盡量覆蓋 ASP.NET / ASP.NETCore 中與 Date/Time有關的歧義、參數(shù)綁定、序列化相關的知識點和坑位。?
Date/Time值歧義和應對策略
使用Datetime最大的問題在于歧義,整個地球分為24個時區(qū),每個時區(qū)都有自己的本地時間
例如一個DateTime值指示了本地時間,這個值在同時區(qū)的其他系統(tǒng)依然標示了同一時間點; 但是在其他時區(qū)以外,這個DateTime值就會有各自的解釋。
電郵中若有
Sun , 04, June 2019 9:45:29 +0800
說明信件發(fā)送第時間是2019年6月04日,星期日,上午9點45分29秒,該地區(qū)領先UTC8小時 (+800,就是東八區(qū)時間)。
對于發(fā)這封郵件的時間,北京本地時9點45,倫敦是凌晨1點45 ......
正因為這個現(xiàn)狀,在Internet以及無線電通信時,時間的統(tǒng)一很重要。
業(yè)界提出了不同的格式來明確地表示單一時間點, Web開發(fā)行業(yè)提出了不同的解決方案以明確定義時間值。
??UTC時間
在國際無線電通信中,為避免各自為戰(zhàn)而普遍使用一個標準時間,稱為協(xié)調(diào)世界時(UTC)
?UTC是0時區(qū)的時間值,與格林威治標準時間(GMT)一樣,都與英國倫敦的當?shù)貢r間相同
UTC能準確代表單一時間點,UTC 時間對于住在加利福尼亞和中國的人來說都是一樣的。
?如果把以上北京時間2019/06/04 09:45:29轉化為UTC時間,可以使用以下公式: UTC + 時區(qū)差 = 當?shù)貢r間。
因為北京時間是東8區(qū),所以這個點UTC時間是 2019/06/04 02:45:29(也可認為該值是倫敦時間)
開發(fā)者可以考慮的解決方案 是: 使用UTC時間存儲date/time、服務端維護、計算也使用UT時間、將UTC時間發(fā)送到瀏覽器,瀏覽器javascript在Web頁上轉化為當?shù)貢r間。
?ISO 8601
Web上有許多時間顯示格式,但最著名并大規(guī)模采用的是ISO-8601 標準。https://www.cl.cam.ac.uk/~mgk25/iso-time.html
當沒有更多信息的時候,只包含Date/Time 的寫法被假定為當?shù)貢r間,要指示該時間是UTC時間,可在Datetime值后面加上字母?z,
在Datetime值后面增加 +hh:mm、 +hhmm, -hh 可指示該時間值相對于UTC時間的偏移
.Net中關于Date/Time的實現(xiàn)
.Net 4.0+ 提供的各種結構已經(jīng)全方位支持 date, timezone, timezone之間的轉化,足以解決開發(fā)者遇到的Date/Time相關的問題。
DateTime
DateTime 定義了一個特殊的date/time, 內(nèi)置的Kind屬性提供了受限的時區(qū)信息:
?、?DateTimeKind.UTC 指定了UTC的DateTime,明確定義了單一時間點
② DateTimeKind.Local 指示了本地時間,這個值在具有相同時區(qū)的其他系統(tǒng)依然能夠定義一個時間點,但是在其他時區(qū)以外,這個DateTime值會有不同解釋。
?、?DateTimeKind.Unspecified 更沒有兼容性,僅表示時間值
我們關注 DateTime.ToUniversalTime() 方法的表現(xiàn),當DateTime被設定為Unspecified時候, ToUniversalTime會首先假定該值是 Local
?when to use datetime?
你只處理當?shù)貢r間,你沒有跨越時區(qū)的計算
你只處理 UTC時間
處理抽象日期/時間(使用 Unspecified):例如跨國公司的跨時區(qū)門店都在早上9點開業(yè)
DateTimeOffset
表示時間點,通常表示為一天中相對于UTC時間的日期/時間,該結構體自然帶有相對于UTC時間的偏移信息
when to use DateTimeOffset?
代碼需要應對不同時區(qū)的時間值
時區(qū)之間相互轉化
需要進行跨時區(qū)的計算
Date/Time 序列化
Web API2 和ASP.NET Core內(nèi)置的JSON序列化器是Newtonsoft.Json,JSON.NET將日期時間序列化為ISO-8601格式:
Date value | serialized value |
DateTime.Now (Pacific time) | 2016-10-11T19:25:34.8346658-07:00 |
DateTime.UtcNow | 2016-10-12T01:25:34.8346658Z |
new DateTime(2016, 6, 6, 4, 5,5 ) | 2016-06-06T04:05:05 |
new DateTimeOffset(new DateTime(2016, 6, 6, 4, 5,5 ), new TimeSpan(-2, 0,0)) | 2016-06-06T04:05:05-02:00 |
ASP.NET MVC 5內(nèi)置的
JSON Serializer?
還是System.Web.Script.Serialization.JavaScriptSerializer, 該序列化器將date序列化為時間戳:“\/Date(ticks)\/”, ticks 表示從1970-1-1 00:00:00 UTC(Unix Epoch)經(jīng)歷的毫秒數(shù),
這樣的格式在客戶端需要使用JavaScript做一些本地轉化, 轉化后的值無法體現(xiàn)時區(qū)。?
JavaScriptSerializer還有更多缺點,現(xiàn)在社區(qū)鼓勵使用Json.Net 序列化器。
Date/Time字符串轉換
在開發(fā)中,常涉及Date/Time 參數(shù)綁定和字符串轉換, 當中也有一些坑位需要規(guī)避。
一個時間日期字符串, 若沒有相對于UTC的偏移信息,轉換后的DateTime對象的DateTimKind是Unspecified;
若指定了offset,轉換后的DateTime對象的DateTimeKind是Local, 并且時間值被調(diào)整到機器的當?shù)貢r間。
最近我們生產(chǎn)環(huán)境WebSite再遷移到k8s集群 (UTC時間)之后,就遇到這樣的問題:
訂單轉儲的預期是:北京時間2019-05-11--->2019-05-12
實際情況是在網(wǎng)站端轉換為Unspecified, 而進一步ToUniversalTime()過濾的時候,該時間段又被假定是機器的當?shù)貢r間, 也就是說查詢時間段變成了: 倫敦時間2019-05-11--->2019-05-12
這樣自然與預期不符。
解決思路: 添加偏移信息,告知明確的時間段: 2019-05-11 00:00:00+08:00 ----> 2019-05-12 00:00:00+08:00
開發(fā)者每天都在使用的Date/Time有很多學問, 涉及Culture、Calendar、夏令時, 這里只是淺談最常用的知識點和坑位。
原文地址:https://www.cnblogs.com/JulianHuang/p/10967289.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?
總結
以上是生活随笔為你收集整理的你需要了解的有关.NET日期时间的必要信息的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NetCore下使用Polly结合IH
- 下一篇: ASP.Net Core MVC 发生二