这是“我”的故事 —— 董彬
點(diǎn)擊藍(lán)字 關(guān)注我們
作者:董彬
校對/文章優(yōu)化:劉軼民
排版:Rani
視頻地址:
https://www.bilibili.com/video/BV1NK4y1p7Ys
與世界周旋的程序員
大家好,我叫董彬 ,現(xiàn)就職于野村信息,??? Title 是 Senior Developer?;仡^看看過去,我覺得還蠻神奇的。雖然我已經(jīng) 30 歲了,但作為一名全職的軟件工程師也僅有一年的時間。有的人會有一些疑問。為什么這么晚才開始做軟件工程師?主要是因?yàn)槲覐?2018 年開始才以邊工作邊讀書的方式,通過遠(yuǎn)程教育的方法拿到了我人生中的第二個碩士學(xué)位,也就是 UIUC 的 Master Ofcomputer Science。
在我上學(xué)的這段期間發(fā)生過一個非常有趣的事情,在我上學(xué)的這段時間發(fā)生過一個非常有趣的事情:我的老師曾經(jīng)在一個期末的時候單獨(dú)表揚(yáng)了我,說我們的董斌同學(xué)每次期末作業(yè),每次的作業(yè)都會提前很早就交上來。這讓我感到非常的奇怪。
因?yàn)槲曳謩e記得我遲交了很多次,后來在和老師核對了之后,才發(fā)現(xiàn)事情的原因。因?yàn)槔蠋熋看卧诹糇鳂I(yè)的時候,他都會說我們的截止時間是 2018年10月1號 CST,那我就想當(dāng)然的以為 CST 和網(wǎng)站上的時間一樣,被自動轉(zhuǎn)換成了東 8 區(qū)的時間,也就是 China Standard Time。但實(shí)際上老師用的是當(dāng)?shù)氐臅r間,也就是美國的中部標(biāo)準(zhǔn)時間(CST)。所以我以為的截止時間要比老師真正上留的這個時間要早上到 14 個小時,這也就是為什么我每次交作業(yè)都要比真正的截止時間要提前很久,不知道有沒有其他的同學(xué)產(chǎn)生了同樣的錯誤(笑)。
CST 同樣還有其他的意思,包括澳大利亞中部時間 (Central Standard Time) 和古巴標(biāo)準(zhǔn)時間(Cuba StandardTime-AUS),時間是一個很美妙的東西,人類為了描述它,引入了很多工具,時區(qū)就是其中之一,時區(qū)是很復(fù)雜的,當(dāng)大家在一個跨國公司工作需要和不同的國家的員工一起協(xié)作,或者是公司本身的產(chǎn)品就服務(wù)于世界各地不同的用戶的話,那么時區(qū)通常情況下都是一個非常令人頭疼的問題,時區(qū)不是以精度進(jìn)行完美的劃分,它有很多種情況。
它既有可能像中國一樣橫跨好幾個時區(qū),但使用的是統(tǒng)一的時區(qū)。也有可能像美國一樣,在同一個國家使用不同的時區(qū)。甚至有可能在印度一樣,雖然只有同一樣的時區(qū),但是它是一個非整數(shù)的時區(qū),而且還有一些國家現(xiàn)在在使用夏令時。這些所有的可能性讓時間的轉(zhuǎn)換變得尤為復(fù)雜。
我所在公司曾經(jīng)有這樣一個 RestfullAPI,它以 Json 的數(shù)據(jù)格式來返回日期,但它返回的日期比數(shù)據(jù)庫中存儲的時間要早上一天。這種情況讓我們感到非常奇怪。在我們調(diào)試的過程中,我們找到了錯誤的原因:首先這個日期是 Java 中的 Date 數(shù)據(jù)類型,當(dāng)它使用 Jdbc 從 Sql Server 中取出這個數(shù)據(jù)的時候,它會被初始化成為一個本地的時間,然后在序列化的時候,他調(diào)用 getTime 方法,得到的是 UTC(1970年1月1日到現(xiàn)在的毫秒數(shù)),所以錯誤產(chǎn)生的原因就是這個本地時間。
雖然他這個服務(wù)器真的就在英國,但是它的時區(qū)是 BST,也就是 Britain Summer Time,它比 UTC 要早上一個小時,所以當(dāng)數(shù)據(jù)庫中的2020年10月1號被 Jdbc 取出來之后,它就變成了2020年9月30號的晚上11點(diǎn)。然而作為 API 消費(fèi)者的我并不知道這個 API 真正的服務(wù)器的時區(qū)在哪里,所以在對其反序列化后就成了2020年9月30號。錯誤就是這樣產(chǎn)生的。為了解決這個問題,我們應(yīng)該怎么辦呢?
一個最普遍的方法當(dāng)然就是把日期以一個格式化的字符串的方式來傳輸出來,那么以格式化的字符串來傳輸,究竟是不是一個很好的選擇呢?在有些情況下其實(shí)也不是。因?yàn)槲覀冞€有另外一個服務(wù),它需要用戶上傳一個 Excel 模板,在這個 Excel 模板里面,我們規(guī)定日期要以 mm/dd/yyyy 的格式來進(jìn)行傳輸,我們在本地調(diào)試的時候是完全沒有問題的,但是交付給用戶的時候,我們就發(fā)現(xiàn)有些用戶總是把日和月寫反,無論怎么樣告訴他他都是寫反。
后來我們仔細(xì)研究了一下,才發(fā)現(xiàn)這個問題出現(xiàn)在 Excel 上面,因?yàn)?Excel 它的日期的默認(rèn)時間格式是與你本機(jī)的語言有關(guān)的,我們在用美式英語來進(jìn)行調(diào)試的時候,mm/dd/yyyy 是完全沒有問題的,但是我們有相當(dāng)一部分內(nèi)部的用戶用的是英式英語,對他們來說,他們的短日期格式就是 dd/mm/yyyy,像這種與語言非常相關(guān)的日期格式,我們在軟件當(dāng)中被稱為 Global Realization 或者是 Internal Realization。我們作為程序員,能力非常有限,不可能了解全世界每一種語言文化的使用習(xí)慣,所以我們是非常依賴于軟件的基礎(chǔ)庫的。?
在2020年11月發(fā)布的 .Net5 當(dāng)中,就有一個與之相關(guān)的破壞性更新。我之所以對這個東西非常有印象,是因?yàn)槲以陂_日歷控件的時候,遇到了這樣一個問題,就是當(dāng)我們在用 Server Side 模式托管我們的控件庫的時候,我們發(fā)現(xiàn)它的日期格式與我們以 WebAssernbly 來托管的時間格式不同。為什么我們同樣的代碼放在不同的托管模式下,會出現(xiàn)這樣的不同。
在請教了 .Net 的官方的工作人員后,他們給我的回復(fù)是這樣的:因?yàn)楫?dāng)我們在本機(jī)調(diào)試的時候以Server Side 端渲染,我們使用的是 Windows 上的 .Net Run Time,它所使用的 i18n 跟 API 是 NLS (National Language Support)。
而當(dāng)我們以 Webassernbly 進(jìn)行托管的時候,他所使用的 Run Time 是 Mono。Mono 作為 .Net 最初的開源實(shí)現(xiàn),它所使用的 i18n 的 API 就是 ICU。ICU是 International Component for Unicode。它是一個被廣泛使用的國際化組件庫,它可以為軟件提供非常好的國際化支持和 Unicode 的支持。
作為中國的用戶,我們可能對于編碼這件事情有非常深刻的理解。比如說我們經(jīng)常打開一些很古老的軟件,它的界面上會有很多亂碼,而且我們也聽說過“燙燙燙”或者是“錕斤拷”,這樣的笑話對吧?那這樣編碼和解碼的錯誤究竟是怎么樣產(chǎn)生的呢?
我們就以“錕斤拷”這個例子來說一下,在 Unicode 中有很多字符是沒有辦法被顯示或者沒有辦法被定義的。在這種情況下,Unicode 的官方為我們提供了一個專門的字符用來解決這種問題,大家可能現(xiàn)在看不到這個字符。這個字符它在 Unicode 中它的編碼是 U+FFD,然后變成二進(jìn)制之后就是下面的這一串。
當(dāng)我們以 UTF8 來進(jìn)行傳輸?shù)臅r候,它就變成第三行的樣子。它的16進(jìn)制格式表示就是下劃線下我們看到的樣子。當(dāng)我們有一連串這樣的字符傳輸過來的時候,如果我們以 GB2312 或者是 GBK 來進(jìn)行反解析的話,我們就會得到"錕斤拷"三個字。
Unicode 是從1990年開始研發(fā)到1994年正式發(fā)布的,而 GB2312 是從1980年就已經(jīng)開始使用了,我們不能說 GB2312 沒有很好的兼容 Unicode,對吧?事實(shí)上的情況就是在 Unicode 正式出現(xiàn)之前,各個國家都有屬于自己的不同的編碼方案,導(dǎo)致各個國家之間的計(jì)算機(jī)系統(tǒng)相互交流有非常大的阻礙。所以 Unicode 的出現(xiàn)很方便的解決了大家的這種跨平臺跨語言之間的通信和交流。
而且中文是受益非常多的,因?yàn)樵?Unicode 中差不多有9萬個中文字符。包括在日本、韓文以及越南正在使用的一些和中國大陸簡體不一樣的字形。而且 Unicode 本身也是在不斷發(fā)展的,它在不斷的吸納新的字符進(jìn)來。比如2019年為了響應(yīng)日本新的年號,他就加入了“令和”,到 Unicode 中。在2020年3月發(fā)布的 Unicode13 當(dāng)中,他收錄了 4000 多個生僻字,其中也包括我們?nèi)f眾期待的 “biangbiang面” 的 “biang” 字。
而在隨著互聯(lián)網(wǎng)時代的發(fā)展,由于后者的更新,還有一個更加大的驅(qū)動力,那就是 emoji,又叫繪文字,他起源自日本,在 iPhone 上大放異彩之后迅速的風(fēng)靡全球,之后就被 Unicode 的官方所接納,成為了它的一個標(biāo)準(zhǔn)之一。emoji 的出現(xiàn)讓大家認(rèn)識到 Unicode 還有非常多的技術(shù)可以挖掘,比如說在人物的 emoji 后面加上 face pattern 的標(biāo)志,我們就可以讓人物呈現(xiàn)不同的膚色????????????????????????????????????????????。
比如說我們可以在嗯嗯,emoji 之間通過零寬連接符進(jìn)行連接,就可以讓不同的人物,不同的性別、不同膚色的人一起組成一個完全不一樣的家庭????????????????????????????????????????????????????????????????????????????????,而這些全部都是 Unicode 本身就能實(shí)現(xiàn)的,emoji 可以說是互聯(lián)網(wǎng)時代人們交流方式改變的一個縮影,通過 emoji 一些語言毫不相通的人也能夠進(jìn)行互相的交流,它也算是一種全新的表意文字了,現(xiàn)在大家可能已經(jīng)習(xí)慣在自己的平常的微信交流中夾雜著幾個 emoji 。這完全沒有問題,對不對??
像這種文化的融合,其實(shí)從新文化運(yùn)動開始,對于中文改革創(chuàng)新來就從來沒有停止過,我們不斷的吸納白話文,簡體字,標(biāo)點(diǎn)。但其實(shí)這些都對中文本身的固有認(rèn)知產(chǎn)生了極大的挑戰(zhàn)。其中一個最大的挑戰(zhàn)就是排版。
對于古人來說,每一個字都是方塊字,從上到下書寫非常的齊整。但是到了現(xiàn)在,我們的中文之間可以夾雜著半寬的數(shù)字,可以夾雜著不等寬的英文字母,還可以帶著標(biāo)點(diǎn),雖然國標(biāo)認(rèn)為標(biāo)點(diǎn)應(yīng)該和字符同寬,但是我們對于標(biāo)點(diǎn)的排版就有額外的要求。比如說我們要避開頭尾、點(diǎn)號不能出現(xiàn)在一行的首部、標(biāo)號的開始不能出現(xiàn)在一行的尾,結(jié)束不能出現(xiàn)在一行的頭。
這些綜合起來看,就對我們軟件的排版產(chǎn)生了一個巨大的挑戰(zhàn)。這里我給大家舉一個微信的例子,這是我自己在微信上進(jìn)行的測試,大家如果看第一行和第二行的話,我會發(fā)現(xiàn)這兩行的字符數(shù)量并不相等,但是他們視覺上看起來長度是一樣的,原因在于為了實(shí)現(xiàn)標(biāo)點(diǎn)的擠壓,微信自動的縮短了每個字之間的間隙。
如果大家看到第二行和第三行的話,就會發(fā)現(xiàn)這種擠壓是因?yàn)闃?biāo)點(diǎn)而引起的,他們擁有相同的字符數(shù),但是因?yàn)榫涮栆驗(yàn)榈谌兴皇且詷?biāo)點(diǎn)結(jié)尾,所以他就可以換行,但是第二行并不可以換行。而第4行就說明這個句號,如果不是出現(xiàn)在行尾的話,它真的就是一個完整的字符串,而不是一個短短的字符。
那么對于英文來說,排版同樣不是輕松的事情,雖然沒有標(biāo)準(zhǔn)懸掛這樣的問題,但是比如說較長的字單詞可能需要按音節(jié)來階段,或者是字母之間,因?yàn)椴荒苡刑箝g隙,所以我們只能調(diào)節(jié)單詞之間的間隙。大家可以意識到僅僅是對于顯示一段文字這樣簡單的一個任務(wù),對于不同的語言來說,就已經(jīng)有如此復(fù)雜的問題出現(xiàn)了,那么其實(shí)還有更多的語言,它在固有認(rèn)知上就已經(jīng)在挑戰(zhàn)我們對于排版,對于軟件界面的這種固有的認(rèn)知。
比如說阿拉伯文,它是從右向左書寫的,那么這就要求很多軟件的界面都要適這種模式?,F(xiàn)在大家看到的就是阿拉伯文的 Windows8 的開始界面,大家可以看到與我們常用的 WindowsOS 是完全鏡像的。但由于伊斯蘭教是目前世界上的三大宗教之一,所以對于阿拉伯文的排版依然有非常巨大的市場。那么對于一些非常小眾的語言,我們又該怎么辦呢?
我是一名內(nèi)蒙古呼倫貝爾人,所以我這里要不得不提一下,我們的回鶻式蒙古文。大家看到這段論文是我在網(wǎng)上隨便看到的,他的意思我并不明白,所以它不代表我的立場,也不代表 MSReactor 的立場?;佞X式蒙古文是從上到下書寫,每個單詞都有不同的長度,那么對于我們現(xiàn)在的這種 UI 的架構(gòu),它就是完全不適用的。至今為止內(nèi)蒙古自治區(qū)依然使用回鶻式蒙古文作為我們的官方語言之一,對于蒙古國而言,他們也將在 2025 年之前完全恢復(fù)使用回鶻式蒙古文。
但是對于現(xiàn)在的各大操作系統(tǒng)軟件來說,回鶻式蒙古文的顯示依然是一個巨大的問題,至今各大操作系統(tǒng)都沒有一個完美的解決方案,只能退而求其次使用西里爾蒙文。
我今天的演講差不多也就到這里結(jié)束了,在故事的最后我想講圣經(jīng)上的一個小故事。在大洪水之后,人們其實(shí)是講著同樣的語言的,大家想齊心協(xié)力建造了無與倫比的巴比倫城,想去建造了一座高塔直通云霄。
這讓上帝感到非常的震驚,所以他就來到了人間,教會了人們使用不同的語言,把人們分散在世界各地。所以這個偉大的巴別塔也就無疾而終了。直到今日我們依然分散在世界的各地,說著不同的語言,用著不同的文字、傳承著不同的文化。但是作為程序員的我們其實(shí)是在通過另一種方式打破這種屏障,與“上帝”進(jìn)行周旋。
我們一方面試圖打破屏障,把世界各地不同的人們聯(lián)系在一起,另一方面我們又在極力的竭盡所能的維護(hù)著這個世界的多樣性。最后我也感謝這個互相連接的世界,能夠給我這個機(jī)會,讓我在遠(yuǎn)14個小時時區(qū)之外的中國能夠完成這個學(xué)業(yè),一起參與到這個偉大的事業(yè)當(dāng)中。
球分享
球點(diǎn)贊
球在看
總結(jié)
以上是生活随笔為你收集整理的这是“我”的故事 —— 董彬的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BeetleX.WebFamily针对W
- 下一篇: BeetleX之Web网关1.5.7安装