ปัญหาเรื่อง พ.ศ. หรือ ค.ศ. ในการเขียนโปรแกรมบน .NET

(post นี้เอามาจากที่เคย post ไว้ที่ bloggang เมื่อนานมาแล้ว แต่ตอนนี้จะย้ายนิวาสมาอยู่ wordpress แล้ว)

เรื่อง Date เนี่ยนะครับ สอนรุ่นน้อง สอนเด็กใหม่ๆ ใครก็ตามที่จะมาเขียนโปรแกรมยุ่งกะ date ไว้เลย
น้องโปรแกรมเมอร์ใหม่ๆ นะครับ ขอได้โปรดทำความเข้าใจความจริงอยู่สามข้อ

1. เวลาที่จะเอา Date มาใส่ String หรือเอา String มาใส่ Date ก็ตาม
เราไม่มีทางรู้ล่วงหน้า ว่าเครื่องที่จะมา run โปรแกรมของเรามันตั้งเอาไว้ยังไง
มันจะแปลงเลขปี ให้เป็น ค.ศ. หรือ พ.ศ.??

2. Date ก็คือ Date ไม่มีคำว่า พ.ศ. หรือ ค.ศ.
การที่เราเห็นเป็นเลข พ.ศ. หรือ ค.ศ. ก็เพียงเพราะการแสดงผลของ environment ขณะนั้นเท่านั้นเอง

3. เราไม่มีทางรู้ล่วงหน้าว่า เวลาที่เราทำ Date เพื่อให้กลายเป็น String
เพื่อเอาไปใส่ SQL ให้ Database (ยี่ห้ออะไรก็แล้วแต่) มัน run แล้วนั้น
Database บนเครื่องที่รันโปรแกรมเรานั้นมันจะมองเลขปีเป็น พ.ศ. หรือ ค.ศ. ??

ผลที่ตามจากความจริงข้อที่ 1 ก็คือ
เราไม่ควรอย่างยิ่ง ที่จะปล่อยให้มีการ convert Date เป็น String (หรือในทางกลับกัน)
โดยไม่ระบุให้ชัดเจนว่าจะเอา พ.ศ. หรือ ค.ศ.
ผมเห็นความพยายามแบบผิดๆ หลายครั้ง ที่พอ convert date เป็น string แล้วได้เลข ค.ศ.
จึงเอาไป + 543 หรือ เอา พ.ศ.ไป – 543 อะไรประมาณนี้
ในข้อนี้ ผมขอแนะนำว่า ถ้าจะมีการเอาตัวเลขปี มาบวกลบหรือใช้ในโปรแกรมยังไงก็แล้วแต่
ควรใช้เลขปีแบบ ค.ศ. ส่วน พ.ศ. นั้น ค่อยให้ไปโผล่ที่ UI เท่านั้นพอ

การ convert Date String โดยบังคับปี ค.ศ. หรือ พ.ศ. ได้นั้น ทำดังนี้ครับ

Dim d as Date
Dim s as String

d = Date.Parse(s, New CultureInfo("en-GB")) ' บังคับ ค.ศ.
d = Date.Parse(s, New CultureInfo("th-TH")) ' บังคับ พ.ศ.

หรือ

s = d.ToString(New CultureInfo("en-GB")) ' บังคับ ค.ศ.
s = d.ToString(New CultureInfo("th-TH")) ' บังคับ พ.ศ.

อย่าไปใช้ CDate ครับ CDate มันเอาไว้ใช้ในเมืองฝรั่งที่เขาไม่ได้มีศักราชใช้หลายอย่างแบบบ้านเรา

ประเด็นสำคัญคือเราต้องกำหนดปฏิทินหรือ Culture เพื่อบอกให้ชัดว่า พ.ศ. หรือ ค.ศ.
และที่ผมเลือกใช้ Culture en-GB ตรงนี้หมายถึง เราต้องการ Format วันเดือนปี (แบบอังกฤษ)
เพราะถ้าเราใช้ en-US มันจะ parse ด้วย Format เดือนวันปี (แบบอเมริกัน)
ซึ่งโดยมากแล้ว application ในบ้านเรา ผมเชื่อว่าถ้าจะใช้ ค.ศ. ก็คงใช้ Format วันเดือนปี

เรื่องต่อมาคือ ผมมักจะได้ยินคำถามอยู่เสมอว่า database ตัวนี้ มันเก็บ ค.ศ. หรือ พ.ศ. ???
คำถามนี้ต้องให้ย้อนกลับไปดูความจริงข้อที่ 2
Date ก็คือ Date มันก็เก็บเป็นแค่ Date ไม่มีคำว่า พ.ศ. หรือ ค.ศ.!

จากนั้นจะมีคำถามต่อมาว่า แล้วเวลาสั่งที่ SQL ต้องให้ใส่ พ.ศ. หรือ ค.ศ.
ก็จะไปเจอความจริงข้อที่ 3
ถ้าเรารู้ล่วงหน้านะครับว่า locale ของ database มันจะรับปีแบบไหน
จะ fix SQL เป็น ค.ศ. หรือ พ.ศ. ก็ตามใจเถอะครับ
แต่ถ้าเราไม่สามารถรู้ล่วงหน้าได้ หรืออยากให้โปรแกรมเรายืดหยุ่นพอล่ะก็
ขอแนะนำให้ใช้ Parameter ส่งตัวแปร Date
จะดีกว่ากันมากครับ ตัดปัญหาเรื่อง ค.ศ. พ.ศ. ไปเลย
แล้วยังทำให้ performance ดีขึ้นอีกด้วย

Dim cmd as New SqlCommand("insert into table1(field1) values @p1", conn)
cmd.Parameters.Add("@p1", d)
cmd.ExecuteNonQuery()

3 Responses to “ปัญหาเรื่อง พ.ศ. หรือ ค.ศ. ในการเขียนโปรแกรมบน .NET”

  1. STP-Soft Says:

    ขอบคุณมากครับปวดหัวมานานกับเรื่องนี้
    คือจะตรวจสอบวันที่กะระบบอัพเดท แต่ตอนนี้ กระจ่างครับ

  2. LekStudio Says:

    ผมว่า Database เก็บเป็นค.ศ.เสมอนะครับ วิธีทดสอบคือให้คุณลองใส่ 29/2/2559 ลงไปใน Database ดูซิครับ มันจะใส่ไม่ได้เพราะมันไม่มีวันที่ 29 เดือน 2 ปีค.ศ. 2559 เพราะปีค.ศ.ปีนั้นมีเดือน 2 แค่ 28 วันครับ

    • panya Says:

      กรณีนี้ “Tool” ที่เราใช้ป้อนต่างหากครับที่มันรับแต่ ค.ศ. ลองถ้า Tool มันเก่งพอจะปฏิบัติตาม Locale ของเครื่องก็อาจป้อน พ.ศ. ได้ นี่แหละครับคือประเด็นที่ผมจะบอกว่า วันเวลา มันไม่มีศักราช มันเป็นแค่จุดหนึ่งของเวลา ซึ่งถูก convert เป็น ค.ศ., พ.ศ., ปีโชวะหรือปีเฮเซ อย่างไรก็ได้ สิ่งที่เราเห็นเกิดจาก Locale ในการทำงานทั้งนั้น ซึ่งต้องคุมตรงนี้ให้อยู่


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: