Custom Search
by  chalitbur   05 Nov 2014
 C#  JAVA  Programming 
นับเป็นปัญหาที่โปรแกรมเมอร์ทุกคนต้องประสบพบเจอ บทความนี้จะพยายามสรุปเรื่องราวเกี่ยวกับ Date Time ที่หลายๆคนสงสัย ให้กระจ่างที่สุดเท่าที่จะทำได้นะครับ ปัญหาที่เจอคืออะไร ? ปัญหาส่วนมากคือเรื่องของ Locale ครับ เช่น ตอนเราพัฒนาโปรแกรมที่เครื่องของเรา มี filed ที่เก็บวันที่ พอเรา design database เราก็กำหนดให้เป็น type Datetime แต่เรามักจะให้ user input เป็น String Format เช่น dd/mm/yyyy ซึ่ง 08/07/2552 ก็หมายถึง วันที่ 08 กรกฎาคม พ.ศ. 2552 พอนำ text ชุดนี้ไป save ลง database ก็มักจะไม่มีปัญหาอะไร (แน่แหละ ถ้ามันบันทึกผิด เราก็ต้องแก้) แต่ปัญหามักจะเกิดตอนที่ เราย้าย code ของเราไปบน server แล้วก็เกิดปัญหาเรื่องของ Locale ขึ้น เช่น server มองว่า 2552 เป็นปี ค.ศ. แทนที่จะเป็น พ.ศ. หรือ 08/07/2552 แทนที่จะมองเป็น วันที่ 08 กรกฎาคม พ.ศ. 2552 กลับมองเป็น วันที่ 07 มิถุนายน พ.ศ. 3095 ซึ่งก็มักจะบันทึกไม่ได้ เกิด error datetime out of range
ทำความเข้าใจกับตัวแปร Type DATETIME
        [C#] System.DateTime : สำหรับ System.DateTime นั้นเป็นตัวแปรประเภท Struct เริ่มต้นจาก 12:00:00 เที่ยงคืนของ January 1, 0001 Anno Domini (Common Era) ถึง 11:59:59 P.M., December 31, 9999 A.D. (C.E.) ซึ่งจริงๆแล้ว ภายใน Struct ก็จะเก็บตัวแปรที่ชื่อว่า Ticks ครับ คราวนี้คำถามก็ตามมาคือ Ticks คืออะไร Ticks ความจริงก็คือตัวเลข Type long ครับ ง่ายๆ คือ ค่าเริ่มต้นของ Datetime คือ 1 มกราคม ค.ศ. 0001 จะมี Ticks = 0 ถัดมาอีก 100-nanosecond ( แบ่ง 1 วินาที ออกเป็น 1,000,000,000 ส่วน จะเท่ากับ 1 nanosecond ) ค่า Ticks จะเท่ากับ 2 แล้วอีก 100-nanosecond ถัดไป Ticks ก็จะเท่ากับ 3 เป็นแบบนี้ไปเรื่อย ดังนั้นหากเราพิมพ์ Ticks ออกมาดู เราก็สามารถคำนวนกลับไปเป็นวันที่และเวลาได้เช่นกัน ลองดูโดยพิมพ์ System.DateTime.Now.Ticks ออกมาดูครับ เราก็จะเห็นค่า Ticks ของเวลาปัญจุบันครับ สังเกต ดูนะครับ ว่าตอนนี้ไม่ว่าเครื่องของเรา จะใช้ปี พ.ศ. หรือ ค.ศ. ค่า Ticks ก็เหมือนกัน สรุปคือ System.DateTime ไม่ได้เก็บ dd/mm/yyyy hh:mm:ss นะครับ แต่เก็บเป็น Ticks !
        [Java] java.util.Date : สำหรับ java.util.Date (Jdk SE 6) เป็นตัวแปร Class ซึ่งพื้นฐานก็อย่างเดียวกับ C# นั่นแหละครับ แต่เริ่มต้น January 1, 1970, 00:00:00 GMT แล้วก็มีหน่วยนับเป็น 1 milliseconds แล้วสิ่งที่ต่างกันอีกอย่างคือ จะไม่มีตัวแปร Ticks ให้เราเรียกตรงๆ หากจะพิมพ์ค่า ปัจจุบันให้เรียกใช้ method System.currentTimeMillis() จะได้ค่า long( เทียบเคียงกับ Ticks ใน C#) หรือ ถ้ามี Instance ของ Class Date อยู่ก็ใช้ method getTime() ได้ เช่น ((Date)( new java.util.Date())).getTime() สรุปคือ java.util.Date ไม่ได้เก็บ dd/mm/yyyy hh:mm:ss นะครับ แต่เก็บเป็น time (Ticks) ! จริงๆแล้วมีเรื่อง Date time เป็นเรื่องที่มีรายละเอียดมากนะครับ ลองอ่านเพิ่มเติมใน java doc ดูได้ครับ
         [DATABASE] Datetime : สำหรับตัวแปรประเภท Datetime ในฐานข้อมูลเกือบทั้งหมดทุกตระกูลก็ใช้หลักการ Ticks นั่นแหละครับ รวมถึง type TimeStamp ด้วย แต่อาจจะต่างกันที่วันเริ่มต้น และ Time values are measured (1 Ticks = เท่าไหร่ เช่น 1 milliseconds หรือ 100 nanoseconds เป็นต้น )ซึ่งเวลาที่เราเขียนโปรแกรม ตัว DB Driver จะเป็นคนจัดการให้ Programming Language ที่เราใช้ เข้ากันกับ Database ที่เราติดต่อด้วย
ปัญหาที่แท้จริงคืออะไร ?
         ความจริงแล้วปัญหาเกือบทั้งหมดที่เกิดขึ้นเกิดจากการ Convert Data Type ไปมาระหว่าง Type DateTime และ Type ต่างๆ (โดยมากจะเป็น String) ทั้งที่ตั้งใจและไม่ตั้งใจ โดยไม่ได้ระบุ Locale หรือ Culture ดังนั้นต้องท่องจำไว้ทุกครั้งนะครับ ว่าการเปลี่ยน data type จาก DateTime ไปเป็น Type อื่น หรือ จาก Type อื่นๆกลับมาเป็น DateTime จะต้องระบุ Locale หรือ Culture ทุกครั้ง อย่าปล่อยให้เป็น Default โดยเด็ดขาด
ตัวอย่าง / Code Sample
         [C#] With parameterized statements : เวลาที่เราจะ Insert ลง Database ที่กำหนด Column เป็น Type DateTime ให้เรามองให้ออกก่อน ข้อมูลที่เรากำลังจะ Insert ขณะนี้มี Type เป็นอะไร ? เช่น
             using (SqlCommand myCommand = new SqlCommand(
             "INSERT INTO USERS (USERNAME,CREATE_DATETIME) VALUES (@username, @now_datetime)", myConnection
                                                                                                  )
                      )
             {
             myCommand.Parameters.AddWithValue("@username", user);
            myCommand.Parameters.AddWithValue("@now_datetime", my_variable);
            myConnection.Open();
            ...................
             }
             ถ้า my_variable เราเป็นตัวแปร Type DateTime เช่น DateTime my_variable = DateTime.Now ; แบบนี้เราก็ไม่จำเป็นต้องระบุ Culture เพราะไม่ได้เกิดการ Convert Datatype ใดๆเลย (ตัวแปรเราเป็น DateTime Database ก็เป็น DateTime เช่นเดียวกัน)
             แต่ถ้า my_variable เราเป็นตัวแปร Type String เช่น String my_variable = "10/07/2552" ; แบบนี้เราจำเป็นแปลงเป็น DateTime ก่อนและต้องระบุ Culture ให้ก่อนไม่เช่นนั้น ตัว Runtime จะใช้ Default ของเครื่องซึ่งจะเกิดปัญหาได้เหมือนที่กล่าวไว้แล้วในตอนตั้น วิธีการ Convert ก็ทำได้ง่ายๆโดย
DateTime dt_my_variable = DateTime.ParseExact("10/07/2552","dd/MM/yyyy",new CultureInfo("th-TH"));
จากนั้นเราก็นำ dt_my_variable ไปใช้แทน myCommand.Parameters.AddWithValue("@now_datetime", dt_my_variable);
         [C#] With String SQL statements : ถ้าเราเขียนแบบ
String sql = INSERT INTO USERS (USERNAME,CREATE_DATETIME) VALUES ('"+str_username+"','"+DateTime.Now+ "')"
แม้ว่าเราจะนำตัวแปรที่เป็น DateTime ไปใส่ แต่ Runtime จะมองว่าเป็นการ Concate String ดังนั้น ตัวแปร type DateTime ของเราก็จะถูกเรียก .ToString() ก่อน ดังนั้นก็มีการแปลง DataType เกิดขึ้น โดยไม่ได้ระบุ Culture ก็จะเป็นปัญแน่นอนครับ แม้เราจะ Insert ผ่านในตอนนี้ เพราะในอนาคตหากเกิดการเปลี่ยน Regional ของ เครื่อง ค่า Culture Defalut ก็จะเปลี่ยนไป ดังนั้นการเขียนแบบนี้ควรงดเว้นนะครับนอกจากนั้นยังอาจจะเสี่ยงต่อการโจมตีด้วย SQL Injection ด้วย
สรุปส่งท้าย
         เมื่อใดก็ตามที่เกิดการแปลง Data Type ระหว่าง DateTime กับ String ให้เราท่องให้ขึ้นใจนะครับ ว่าต้องระบุ Culture หรือ Locale ด้วยทุกครั้ง
        แปลงจาก DateTime ไปเป็น String ก็ต้องระบุว่าว่า เราต้องการ String แบบไหน (วันเดือนปี หรือ ปีเดือนวัน) และ Culture แบบไหน ถ้าแสดงเป็น พ.ศ. ก็ต้อง ("th-TH") ถ้า ค.ศ. ก็ต้อง ("en-US") เช่น DateTime.Now.ToString("yyyy/MM/dd",new CultureInfo("th-TH"));
        แปลงจาก String ไปเป็น DateTime ก็ต้องระบุว่า String ของเรา จุดไหนเป็น ปี เดือน วัน ("dd/MM/yyyy") หรือ ("yyyy/MM/dd") และ String ของเรามาเป็น ค.ศ. หรือ พ.ศ. เช่น DateTime.ParseExact("10/07/2552","dd/MM/yyyy",new CultureInfo("th-TH"));

แค่นี้เราก็จะหลีกเลี่ยงปัญหาปวดหัวที่จะตามมาได้แล้วครับ
#1

test 

Post Your Comment
Please Login
Android Developer - ติดตั้ง Android Studio ใน Windows
by  chalitbur   02 Feb 2015
 android studio  ติดตั้ง  setup 

ก่อนที่เราจะเริ่มเขียนโปรแกรมบน Android สิ่งแรกที่ต้องทำก็คือการติดตั้ง IDE ซึ่งในอดีตเราจะต้องทำการเขียนโปรแกรมผ่าน Eclipse IDE ซึ่งจะ Download มาพร้อมกับ ADT แต่ปัจจุบัน Google ได้พัฒนา IDE Tools ตัวใหม่สำหรับให้นักพัฒนาได้ Download กับไปใช้สำหรับพัฒนาโปรแกรมชื่อ Android Studio วันนี้เราลองมาเริ่มติตตั้งเพื่อเตรียมความพร้อมสำหรับการสร้างสรรค์โปรแกรมในโลกของ Android กัน

ทำความรู้จักกับ Microsoft .NET Native
by  chalitbur   21 Nov 2014
 .NET  .NET Native 

.NET Native คือเทคโนโลยีในการ precompilation สำหรับสร้างและนำ application ส่งขึ้นไปยัง Windows Store. โดยจะเป็นการคอมไพล์โค๊ดที่เขียนด้วย Managed Code ( C# ) และทำการคอมไพล์เป็น Code แบบ Native (ภาษาเครื่อง) โดยปกติแล้ว application ที่เราเขียนด้วย .NET Framework จะถูกคอมไพล์เป็น Intermediate Language ( IL ) ขณะที่โปรแกรมเริ่มทำงาน Just-In-Time (JIT) Compiler จะแปลง IL ไปเป็น Native Code.   ซึ่่ง.NET Native ตัวนี้จะแปลง Windows Store application ที่เรา ทำขึ้นไปเป็น Native Code เลยทันที นั่นหมายความว่า