Date.prototype.toLocaleString()

mdn မှာရှာဖတ်ကြည့်လိုက်ရင်တော့ toLocaleString ကိုခေါ်ရင် string တစ်ခု return ပြန်မယ်

string သည် လူတွေဖတ်လို့နားလည်လို့လွယ်တဲ့ format အတိုင်းကို Intl.DateTimeFormat implementation အတိုင်းဖြစ်မယ်

ဒီလောက်ပဲရေးပြထားတယ် ဒါကိုပဲဖတ်ပြီး ကိုယ့် code ထဲမှာ ယူသုံးလိုက်တယ်ပေါ့

ဥပမာ Date နှစ်ခုရဲ့ ခြားနားချက်ကိုလိုချင်တယ်ဆိုပါစို့

ခြားနားချက်ကိုရှာဖို့အတွက် လုပ်လို့ရတာနှစ်နည်းရှိမယ်

Local အနေနဲ့ထားပြီးရှာတာရယ်

UTC အနေနဲ့ထားပြီးရှာတာရယ်

ဘာအနေနဲ့ထားပြီးရှာမှာလဲဆိုတာကတော့

ကိုယ့် data ပေါ်မှာပဲမူတည်မယ်ပေါ့

ဆိုပါစို့ data သည် UTC တန်ဖိုးအနေနဲ့လာတယ်ထားပါတော့

const date1 = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
const date2 = new Date(Date.UTC(2012, 11, 20, 2, 0, 0));

UTC အနေနဲ့ကတော့ရှင်းပါတယ်

console.log(date1 - date2)
// Expected: 3600000

Local အနေနဲ့ ပြန်ပြောင်းပြီးရှာကြည့်ကြပါစို့

const local1 = new Date(date1.toLocaleString());
const local2 = new Date(date2.toLocaleString());
console.log(local1 - local2)
// Expected: 3600000

ဒါဆိုလိုချင်တဲ့ ခြားနားချက်ရသွားပြီလားပေါ့

ကိုယ်တိုင် run ကြည့်နိုင်ပါတယ်

အဖြေက ဘယ်ပေါ်မှာမူတည်သလဲဆိုတော့ JavaScript Engine ပေါ်မှာပဲမူတည်ပါတယ်

ဥပမာ

MacOS Chrome -> v8 ဖြစ်မယ်

IOS Chrome -> WebKit ဖြစ်မယ်

vendor တွေရဲ့ policy တွေအရ JS Engine တစ်ခုနဲ့တစ်ခုကွဲနိုင်ပါတယ်

သတိထားရမှာက Browser အမျိုးအစား ကွဲခြင်းထက်

သူတို့သုံးထားတဲ့ JS Engine အပေါ်မှာပဲမူတည်ပါတယ်

local အနေနဲ့ရှာထားတဲ့အဖြေမှာ လက်ရှိ code အရ

JS Engine မတူတဲ့အပေါ်မှာမူတည်ပြီး

v8 မှာ 3600000 ရပေမယ့်

webKit မှာတော့ NaN (Not a Number) ပဲရပါတယ်

ရေးထားတဲ့ code ချင်းတူပေမယ့်

သူတို့ရဲ့ semantics တွေဟာ JS Engine တွေရဲ့ implementation ကွာသွားတဲ့အတွက်

ရလဒ်ကလည်း ကွဲပြားသွားပါတယ်

ဘာကြောင့် NaN ရသလဲဆိုတာရှင်းပြပါမယ်

ပြဿနာရဲ့အရင်းမြစ်က toLocaleString ရဲ့ return value ဟာ

v8 မှာဆိုရင် အောက်ကအတိုင်းဖြစ်ပါတယ်

date1 => 12/20/2012, 10:00:00 AM
date2 => 12/20/2012, 9:00:00 AM

webKit မှာဆိုရင်

date1 => 20/12/2012, 10:00:00
date2 => 20/12/2012, 09:00:00

ဒီလိုကွဲနေပါတယ်

v8 မှာသုံးသွားတဲ့ locale နဲ့

webKit မှာသုံးသွားတဲ့ locale မတူတာဖြစ်ပါတယ်

v8 မှာတော့ default အနေနဲ့ en-US ဖြစ်ပြီး

webKit မှာတော့ default အနေနဲ့က en-GB ဖြစ်ပါတယ်

US မှာ AM, PM နဲ့သုံးပေမယ့်

Great Britain မှာတော့ 24 hour format နဲ့သုံးတာဖြစ်ပါတယ်

သေချာသွားအောင် အောက်ပါအတိုင်း စမ်းကြည့်လို့ရပါတယ်

console.log(date1.toLocaleString('en-US'))
console.log(date1.toLocaleString('en-GB'))

ဒီအထိ code ဟာ မှန်မှန်ကန်ကန်အလုပ်လုပ်ပါသေးတယ်

ဘယ်မှာ ပြဿနာဖြစ်သလဲဆိုတော့

Date Constructor မှာဖြစ်ပါတယ်

Date Constructor က Date String ကိုလက်ခံနိုင်ပါတယ်

ဒါပေမယ့် Date String အကုန်လုံးကိုတော့ လက်မခံနိုင်ပါဘူး

ဒီနေရာမှာဆိုရင် en-US ရဲ့

12/20/2012, 10:00:00 AM ဒီ format ကိုလက်ခံပေမယ့်

en-GB ရဲ့ format ဖြစ်တဲ့ 20/12/2012, 10:00:00 ကိုတော့လက်မခံနိုင်ပါဘူး

ဒါကြောင့်သူလက်မခံနိုင်တဲ့ en-GB format ဖြစ်တဲ့

20/12/2012, 10:00:00 ဒီတန်ဖိုးကို အောက်ကအတိုင်းထည့်ပေးလိုက်တဲ့အခါ

new Date(date1.toLocaleString())

Invalid Date ဆိုတဲ့ string ကိုပဲ return ပြန်ပါတယ်

ဘာကြောင့်လဲဆိုရင်

Date constructor ရဲ့ အလုပ်လုပ်ပုံသည် Date.parse အလုပ်လုပ်တဲ့ပုံစံနဲ့အတူတူပဲဖြစ်ပါတယ်

သူလက်ခံတဲ့ ပုံစံက အောက်ကအတိုင်းရှိပါတယ်

Date.parse(x.toString())
Date.parse(x.toUTCString())
Date.parse(x.toISOString())

ဒီအထက်ကဟာတွေနဲ့ဆိုရင်တော့ ပြဿနာမရှိနိုင်ပါဘူး

Date.parse(x.toLocaleString())

ဒီမှာဆိုရင် toLocaleString() ကနေရတဲ့တန်ဖိုးသည် implementation လုပ်ထားတဲ့အပေါ်မှာမူတည်ပြီး

ကွဲနိုင်တာမို့ ပြဿနာရှိနိုင်ပါတယ်ဆိုပြီး ECMA Spec မှာဖော်ပြထားပါတယ်

ဒါကြောင့် Date constructor သည် en-US locale ဖြစ်တဲ့ AM PM format ကိုလက်ခံပြီး

သူလက်မခံတဲ့ en-GB format ကိုတော့ "Invalid Date" အဖြစ် return ပြန်ပေးတာဖြစ်ပါတယ်

ဒါကြောင့် NaN ရတဲ့ case မှာဆိုရင်

local1 - local2 လုပ်တဲ့အခါမှာ

"Invalid Date" - "Invalid Date" ဖြစ်နေပါတယ်

Number convertion လုပ်လို့မရတဲ့ တန်ဖိုးတွေဖြစ်တာကြောင့်

NaN - NaN ဖြစ်သွားပါတယ်

NaN - NaN ဆိုတော့ NaN ပဲရပါတယ်

ဒါကြောင့် web developer တွေ code ရေးတဲ့အခါမှာ ရေးပြီးရုံနဲ့မပြီးဘဲ

JS Engine အလိုက် semantics ကွဲတာတွေကို သတိထားနိုင်ဖို့လိုပြီးတော့

Browser Compatibility Testing လည်း မဖြစ်မနေလုပ်ဖို့ အရမ်းအရေးကြီးပါတယ်

Last updated