DEV Community

Pallat Anchaleechamaikorn
Pallat Anchaleechamaikorn

Posted on

time format ใน Go

บังเอิญผมได้ไปเห็นการใช้ date time format ใน Go แบบผิดๆอยู่บ่อยๆ ก็เลยอยากมาอธิบายเรื่องนี้สักเล็กน้อย

หลายคนอาจจะรู้อยู่แล้วว่าวิธีการจัดการ date time format ใน Go มันจะไม่เหมือนภาษาอื่นที่เขามักจะใช้อักษรแทนเช่น dd คือวันที่ MM คือเลขเดือน yyyy คือปี คศ 4 หลัก และในส่วนของเวลาก็ใช้ hh:mm อะไรแบบนี้ ใน Go จะใช้เลขเรียง 1 2 3 4 5 6 7 มาแทนเพื่อให้จำง่าย(ง่ายตรงไหน)
ซึ่งก็มีหลายคนชื่นชมวิธีคิดแบบนี้ และในขณะเดียวกัน ก็มีคนสรรเสริญไปในทางลบค่อนข้างมากเช่นกัน ซึ่งเหตุผลในส่วนคนที่ชื่นชมก็มองว่า ถ้าคุณจำ magic order ได้ คุณก็ไม่ต้องจำมันอีกต่อไป ซึ่ง Rob Pike เคยมาเฉลยว่า เขาคิดเรื่องนี้ได้ตอนกลับบ้าน แล้วนึกถึงวิธีที่ภาษาโคบอลใช้ ซึ่งเรียกว่า Cobol picture clauses ทั้งๆที่เขาเองก็ไม่เคยเขียน Cobol นะ ส่วนคนที่ไม่ชอบก็ติว่า ทีใน fmt ใช้ %s %d กันสนุกเลย แต่พอมา time format กลับเลี่ยงที่จะทำเหมือนชาวบ้านเขาที่ใช้ %d %Y หรือ ddyy ทำไม มันทำให้ต้องมาจำอะไรแปลกๆเพิ่มขึ้นอีก ก็นะ ส่วนตัวผม ก็ดันชอบการคิดอะไรใหม่ๆอยู่แล้ว แต่ก็ไม่เถียงว่ามันก็ต้องมานั่งจำกันใหม่จริงๆนั่นแหล่ะ เอาล่ะมาเล่าเรื่อง time format กันต่อ โดยตัวแทนแต่ละเลขเป็นดังนี้

1 = เดือน
2 = วัน
3 = ชั่วโมง
4 = นาที
5 = วินาที
6 = ปี
7 = time zone

เห็นไหมว่ามันจำง่่าย (ย้ำว่าง่ายตรงไหน) เช่น "01/02 03:04:05PM '06 -0700" นี่คือหน้าตาของ format นะครับ ไม่ใช่เวลาจริง ส่วนเวลาจริง ถ้าตัวเลขตามนี้เป๊ะมันหมายถึง

วันที่ 2 เดือน มกราคม ปี 2006 เวลา 15 นาฬิกา 4 นาที 5 วินาที ณ time zone ที่ -7 ซึ่งคือเวลาแถวๆประเทศเม็กซิโก ซึ่งตรงกับเวลา 22 นาฬิกา หรือ 4 ทุ่ม 4 นาที 5 วินาที ที่ตำแหน่ง UTC ที่ลอนดอน

ทีนี้ เนื่องจาก format ที่ใส่ -0700 เข้าไปนี่ อาจจะทำให้คนที่ไม่ได้อ่าน doc ตีความกันไปเองว่า ไอ้แถวๆนี้มันน่าจะสามารถใส่อย่างอื่นเข้าไปแทนได้เช่น +0700 หรือ +0000 แต่ความจริง นี่มันเป็น format ซึ่งท่าบังคับมันคือจะต้องเป็น -0700 ไปใส่เครื่องหมาย + ให้มันไม่ได้จ้า และเลขก็ต้องเป็นเลข 7 ซึ่งเป็นเลขเรียงอย่างที่กล่าวไปแล้วข้างต้น

Month = 1

สามารถใช้ได้ 4 รูปแบบ

  • Jan กรณีต้องการเป็นอักษรย่อ 3 ตัว เช่นถ้า data เป็น Mar เราอยากจะ parse เข้ามาใส่ time.Time เราก็ต้องใช้ Jan แทนค่านั้นใน format
  • January กรณีต้องการคำเต็มของเดือนเช่น ถ้า data เป็น March เราก็ต้องใช้ January เป็น format สำหรับ parse
  • 01 กรณีที่ data เป็นเลข 2 หลักแทนเดือน
  • 1 กรณีที่ data เป็นเลขที่ไม่ต้องการให้มี 0 นำหน้าสำหรับเดือนที่มี 1 digit เช่น เดือน มีนา ก็จะเป็นเลข 3 เลย

Day = 2

day จะพิเศษหน่อย เนื่องจากวันมีหลายความหมาย

วันในสัปดาห์เช่น จันทร์ อังคาร พุธ

วิธีใช้ สามารถใช้ได้ทั้ง

  • "Mon"
  • "Monday"

จะมาใช้ "mon" แบบนี้ไม่ได้นะ

วันในเดือนก็คือวันที่

สามารถใช้ได้ 3 รูปแบบคือ

  • "2"
  • "02"
  • "_2" ตัวนี้ถ้าเราจัด format ออกมาจะได้รูปแบบ 2 digits แต่ถ้าเป็นเดือนหลักเดียว มันจะเว้นวรรคให้เช่นถ้าเดือน 3 จะได้ " 3" แต่ถ้าเดือน 10 จะได้ "10" แบบนี้

วันที่ของปี ซึ่งมีได้ 365 หรือ 366 วัน

มี 2 รูปแบบคือ

  • "002"
  • "__2" ก็เหมือนวันของเดือน โดยจะเว้นวรรคและแสดงให้ครบ 3 digits

Hour = 3

15" "3" "03" (PM or AM)
มี 3 รูปแบบคือ

  • "15"
  • "3" หรือ "3 PM"
  • "03" หรือ "03 PM"

การใส่ PM จะช่วยเพิ่มรายละเอียดให้การบอกเวลาแบบ 12 hour clock ให้รู้ว่าเป็นเวลาก่อนเที่ยง(ante merīdiem หรือ “before midday”) หรือหลังเที่ยง(post merīdiem หรือ "before midday") ซึ่งจะไม่สามารถใช้ AM แทนได้นะ อย่าสับสน นี่คือการจัด format เด้อ มันบังคับให้ใช้ได้แค่ "PM"

Minute = 4

มี 2 รูปแบบ

  • "4"
  • "04"

Second = 5

มี 2 รูปแบบ

  • "5"
  • "05"

Year = 6

มี 2 รูปแบบ

  • "2006"
  • "06"

Time zone = 7

ก่อนอื่นต้องทำความเข้าใจเรื่อง Time zone ก่อนว่าเราจะใช้มาตรฐาน UTC (Universal Time Coordinated) ซึ่งเป็นเวลาสากลเชิงพิกัด โดยจะใช้พิกัดเส้นลองจิจูด ที่ 0° เป็นจุดอ้างอิงว่าเป็น UTC-0 ซึ่งที่ตำแหน่งนั้น มันเป็นเส้นที่ตัดผ่านหอดูดาวหลวงกรีนิช ที่ลอนดอน ซึ่งแต่เดิมจะใช้เวลาจากหอดูดาวนี้ เป็นมาตรฐานเทียบเวลา เรียกว่า GTM (Greenwich Mean Time) แต่นั่นจะถือเป็นมาตรฐานเก่ากว่านะครับ เนื่องจากเป็นเวลาที่อ้างอิงตามหลักดาราศาสตร์ ปัจจุบันให้เปลี่ยนไปใช้ UTC ซึ่งอ้างอิงตามตำแหน่งพิกัดเส้นลองจิจูดแทน
และยังมี MST (Mountain Standard Time) ซึ่งเป็นเวลาอ้างอิงเวลามาตรฐานกับเวลาที่เทือกเขาร็อกกี้ ซึ่งจะเท่ากับ UTC-7 พอดี ทำให้เราก็จะสามารถใช้ MST มาเป็นหนึ่งใน Format ของเราได้ด้วย

มาดู format ของ time zone แบบเบื้องต้นที่ต้องการ parse time zone ในรูปแบบใช้เครื่องหมาย +/- ตามปกติกัน จะใช้รูปแบบนี้ คือต้องเป็น เครื่องหมายลบ "-" เท่านั้น และเลขต้องป็นเลข 7 เท่านั้น ซึ่งพอเอาไป parse เวลาจริง ถ้ามันจะมาเป็น +0800 ก็จะไปตรงกับ format "-0700" แต่ถ้าข้อมูลมาเป็น "+08" ก็ใช้ format "-07" เป็นต้น

"-0700" ±hhmm
"-07:00" ±hh:mm
"-07" ±hh
"-070000" ±hhmmss
"-07:00:00" ±hh:mm:ss

ต่อมาเป็นแบบ ISO 8601

"Z0700" Z or ±hhmm
"Z07:00" Z or ±hh:mm
"Z07" Z or ±hh
"Z070000" Z or ±hhmmss
"Z07:00:00" Z or ±hh:mm:ss

ตัว Z หรือจะเรียกว่า Zulu ก็ได้ไม่ผิด เป็นสัญลักษณ์ที่ใช้วางไว้หลังเวลาวิธีใช้ก็แค่ใช้แทนเครื่องหมายลบ เท่านั้น เวลาแสดง format ก็จะมาในรูปแบบ +/- เหมือนเดิม

MST ก็คือ time zone format เวลาที่เราต้องการ parse ตัว time zone ที่เป็นแบบระบุ time zone เช่น EST หรือ PST และแม้แต่จะ custom เองก็ได้เช่นกันผ่าน time.FixedZone

เล่าไว้เท่านี้นะครับ สามารถอ่านให้ละเอียดมากกว่านี้ที่ https://pkg.go.dev/time และเพิ่มความเข้าใจผ่านการทดลองด้วยตัวเองดูจะดีกว่านะครับ

Top comments (0)