駁Fish Li 在文章《ASP.NET常被忽視的一些細節》 對.Net JavaScriptSerializer處理DateTime的誤解

來源:互聯網
上載者:User

Fish Li今天發了一篇火爆的《ASP.NET常被忽視的一些細節》,其中有一個地方我認為他大大的冤枉了微軟.Net 類庫設計人員,你開啟連結就直接跳到了重點,先直接粘貼過來引用如下:

Fish Li DateTime的JSON序列化

在SP.NET3.5中,微軟為ASP.NET為設計了一個JSON序列化的工具類, System.Web.Script.Serialization.JavaScriptSerializer,這個類的使用很廣泛,而且比WCF的那個JSON序列化類別的相容性要好。 不過,這個類有一個問題,在序列化DataTime類型時,它產生的結果會讓所有人感覺彆扭, 其實序列化的結果表現形式還個小問題,在前端寫個轉換函式就能解決, 然而,如果你需要 用序列化和還原序列化的方法來做對象的持久化,就會遇到問題,例如下面的代碼:

DateTime dt1 = DateTime.Now;JavaScriptSerializer jss = new JavaScriptSerializer();string json = jss.Serialize(dt1);DateTime dt2 = jss.Deserialize<DateTime>(json);context.Response.Write(dt1 == dt2);

瀏覽器顯示的結果會讓人感到很意外,竟然是:False

出現這個原因與JavaScript的時間格式有關,它使用了UTC時間, 不過,這個理由讓人感到難以接受,畢竟其它的還原序列化都能還原對象,例如二進位序列化和XML都能正確的還原對象。 沒辦法,這裡只能算是個坑了,所以,如果你要做對象的持久化操作,盡量不要選擇JSON序列化。

 以上抱怨其實是沒有對javascript時間有正確的理解 , 在mozilla開發人員網路看了一篇文章, 介紹js Date對象的 , 詳情見:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FDate 

截取其中一段對Date對象的描述原文如下: 

Description

If you supply no arguments, the constructor creates a JavaScript Date object for today's date and time according to local time. If you supply some arguments but not others, the missing arguments are set to 0. If you supply any arguments, you must supply at least the year, month, and day. You can omit the hours, minutes, seconds, and milliseconds.

The JavaScript date is measured in milliseconds since midnight 01 January, 1970 UTC. A day holds 86,400,000 milliseconds. The JavaScript Date object range is -100,000,000 days to 100,000,000 days relative to 01 January, 1970 UTC.

The JavaScript Date object provides uniform behavior across platforms.

The JavaScript Date object supports a number of UTC (universal) methods, as well as local time methods. UTC, also known as Greenwich Mean Time (GMT), refers to the time as set by the World Time Standard. The local time is the time known to the computer where JavaScript is executed.

Invoking JavaScript Date in a non-constructor context (i.e., without the new operator) will return a string representing the current time.

黑體部分是重點中的重點,大意是: javascript 日期以1970年1月1日的世界標準時的到現在的毫秒數計量,一天有86400000毫秒, js日期範圍是世界標準時1970年1月1日之前的100000000天到其後的100000000天。

下面我們來看看MSDN上微軟對JavaScriptSerializer 對象的說明,參見連結:http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx 

下面是對.net類型和json類型的映射表格的一個, 詳細見上面連結:

 以上說明了.NET DateTime 轉換為JSON格式是以javascript標準日期為基準, 以1970-1-1半夜與當前UTC格式日期相隔的毫秒數為轉換結果,這樣我們在js中我們可以用Date對象內建函數隨意轉換為本地格式或其他格式,這樣 Fish Li所言的“不過,這個類有一個問題,在序列化DataTime類型時,它產生的結果會讓所有人感覺彆扭, 其實序列化的結果表現形式還個小問題,在前端寫個轉換函式就能解決” 就完全不是問題了, 因為根本不需要寫什麼轉換函式,下面是測試代碼:

            DateTime now = DateTime.Now;            Console.WriteLine(now.ToString());            JavaScriptSerializer js = new JavaScriptSerializer();            string json = js.Serialize(now);            Console.WriteLine(json);

 執行結果如下:

將JSON字元結果放到javascript中運行如下: 

以上說明其序列化結果表現形式在js環境中完全不是問題, 那在持久化處理中有大問題嗎, 還是以Fish Li 的代碼來說明: 

DateTime dt1 = DateTime.Now;JavaScriptSerializer jss = new JavaScriptSerializer();string json = jss.Serialize(dt1);DateTime dt2 = jss.Deserialize<DateTime>(json);context.Response.Write(dt1 == dt2);

瀏覽器顯示的結果會讓人感到很意外,竟然是:False   

 其實只要在還原序列化時不要忘記轉換為本地時,問題就解決了:(因為我們中國在東八區,所以utc時間早了8小時)   我回複了 Fish Li, 他回複“你能不能再想遠點呢?
你要寫的是通用的代碼,不僅只處理一個DateTime類型,你不知道哪個類型中有DateTime屬性,你打算怎麼辦?” 這其實很好解決,如果真要使用本地時間, 應用完全不考慮國際化: 完全可以在含有DateTime成員的類中再加一個String 類型的成員, web介面處理時,只用顯示DateTime的String值就可以了, 甚至如完全用一個String類型的DateTime就ok了,再要儲存到資料庫時再轉回DateTime。。 例如:
class Test    {        private DateTime date = DateTime.Now;        /// <summary>        /// Datetime format Date        /// </summary>        public DateTime Date        {            get            {                return date;            }            set            {                date = value;            }        }        /// <summary>        /// String format Date        /// </summary>        public String DateString        {            get            {                return date.ToString();            }        }    }

其實主流的JSON轉換函式都是如MS庫相同處理,所以我沒法想到一個比標準還標準的所謂通用解決方案了  哎, 今天又沒多少時間寫win8 部落格園用戶端了 。。 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.