บ่อยครั้งที่ฉันพบข้อเสนอแนะเชิงลบเกี่ยวกับ Java Date
และคลาสอื่น ๆ ที่เกี่ยวข้องกับวันเวลา ในฐานะนักพัฒนา. NET ฉันไม่สามารถเข้าใจได้อย่างเต็มที่ (โดยไม่ได้ใช้) ว่ามีอะไรผิดปกติกับพวกเขา
มีใครให้ความกระจ่างเกี่ยวกับเรื่องนี้ได้บ้าง?
บ่อยครั้งที่ฉันพบข้อเสนอแนะเชิงลบเกี่ยวกับ Java Date
และคลาสอื่น ๆ ที่เกี่ยวข้องกับวันเวลา ในฐานะนักพัฒนา. NET ฉันไม่สามารถเข้าใจได้อย่างเต็มที่ (โดยไม่ได้ใช้) ว่ามีอะไรผิดปกติกับพวกเขา
มีใครให้ความกระจ่างเกี่ยวกับเรื่องนี้ได้บ้าง?
คำตอบ:
อ่าDate
คลาสJava บางทีอาจเป็นหนึ่งในตัวอย่างที่ดีที่สุดในการไม่ทำบางสิ่งในภาษาใดก็ได้ทุกที่ ฉันจะเริ่มจากตรงไหนดี?
การอ่าน JavaDoc อาจทำให้เราคิดว่านักพัฒนามีความคิดที่ดี มันจะไปเกี่ยวกับความแตกต่างระหว่างเวลา UTCและเวลา GMTที่มีความยาวแม้จะมีความจริงที่ว่าแตกต่างระหว่างสองเป็นพื้นเผ่นวินาที (ซึ่งเกิดขึ้นสวย ไม่ค่อย )
อย่างไรก็ตามการตัดสินใจในการออกแบบนั้นทำให้เสียความคิดที่จะเป็น API ที่ออกแบบมาอย่างดี ข้อผิดพลาดที่ชอบมีดังนี้
null
. เป็นผลให้เรามี 0..11 (และวันนี้เป็นเดือนที่ 11 ของปี 109) มีจำนวน ++ และ - ใกล้เคียงกันในเดือนเพื่อที่จะแปลงเป็นสตริงCalendar
ออกแบบมาเพื่อ 'แก้ไข' สิ่งนี้ทำให้เกิดข้อผิดพลาดเดียวกัน พวกเขายังคงไม่แน่นอนDate
แสดงถึง a DateTime
แต่เพื่อที่จะเลื่อนไปสู่สิ่งที่อยู่ใน SQL land จึงมีคลาสย่อยอื่นjava.sql.Date
ซึ่งแสดงถึงวันเดียว (แม้ว่าจะไม่มีเขตเวลาที่เกี่ยวข้องก็ตาม)TimeZone
s ที่เกี่ยวข้องกับ a Date
ดังนั้นช่วง (เช่น 'ทั้งวัน') มักจะแสดงเป็นเที่ยงคืน - เที่ยงคืน (มักจะอยู่ในเขตเวลาที่กำหนดเอง)สุดท้ายเป็นที่น่าสังเกตว่าโดยทั่วไปแล้วอธิกวินาทีจะแก้ไขตัวเองเทียบกับนาฬิการะบบที่ดีซึ่งอัปเดตด้วย ntp ภายในหนึ่งชั่วโมง (ดูลิงก์ด้านล่าง) โอกาสที่ระบบจะยังคงทำงานอยู่ในการเปิดตัวสองวินาทีอธิกสุรทิน (ทุก ๆ หกเดือนขั้นต่ำทุกๆสองสามปีในทางปฏิบัติ) นั้นไม่น่าเป็นไปได้มากนักโดยเฉพาะอย่างยิ่งเมื่อพิจารณาถึงความจริงที่ว่าคุณต้องปรับใช้รหัสเวอร์ชันใหม่เป็นครั้งคราว . แม้แต่การใช้ภาษาแบบไดนามิกที่สร้างคลาสหรือบางอย่างเช่นเครื่องมือ WAR จะทำให้พื้นที่ของชั้นเรียนเป็นมลพิษและหมดสิทธิ์ในที่สุด
JSR 310ซึ่งแทนที่คลาสวันที่และเวลาเก่าด้วยjava.timeใน Java 8 จะระบุตัวเองในJSR ดั้งเดิมดังนี้:
2.5 อะไรคือความต้องการของชุมชน Java ที่จะได้รับการแก้ไขโดยข้อกำหนดที่เสนอ?
ปัจจุบัน Java SE มี API วันที่และเวลาแยกกันสองรายการ - java.util.Date และ java.util.Calendar API ทั้งสองถูกอธิบายอย่างสม่ำเสมอว่านักพัฒนา Java ใช้งานยากบนเว็บบล็อกและฟอรัม โดยเฉพาะอย่างยิ่งทั้งสองใช้ดัชนีศูนย์เป็นเวลาหลายเดือนซึ่งเป็นสาเหตุของข้อบกพร่องมากมาย ปฏิทินยังได้รับความเดือดร้อนจากข้อบกพร่องและปัญหาด้านประสิทธิภาพมากมายในช่วงหลายปีที่ผ่านมาสาเหตุหลักมาจากการจัดเก็บสถานะในสองวิธีที่แตกต่างกันภายใน
ข้อบกพร่องแบบคลาสสิกข้อหนึ่ง (4639407) ป้องกันไม่ให้สร้างวันที่ที่แน่นอนในวัตถุปฏิทิน สามารถเขียนลำดับของรหัสที่สามารถสร้างวันที่ในบางปี แต่ไม่สามารถสร้างวันที่อื่นได้โดยมีผลในการป้องกันไม่ให้ผู้ใช้บางรายป้อนวันเกิดที่ถูกต้อง สิ่งนี้เกิดจากคลาสปฏิทินอนุญาตให้เพิ่มเวลาออมแสงได้เพียงหนึ่งชั่วโมงในฤดูร้อนเมื่อในอดีตเป็นเวลาบวก 2 ชั่วโมงในช่วงสงครามโลกครั้งที่สอง ในขณะนี้ข้อบกพร่องนี้ได้รับการแก้ไขแล้วหากในอนาคตประเทศหนึ่งเลือกที่จะเพิ่มเวลาออมแสงบวกสามชั่วโมงในช่วงฤดูร้อนคลาสปฏิทินจะเสียอีกครั้ง
Java SE API ปัจจุบันยังทนอยู่ในสภาพแวดล้อมแบบมัลติเธรด คลาสที่ไม่เปลี่ยนรูปเป็นที่รู้กันว่าเธรดปลอดภัยโดยเนื้อแท้เนื่องจากสถานะไม่สามารถเปลี่ยนแปลงได้ อย่างไรก็ตามทั้งวันที่และปฏิทินสามารถเปลี่ยนแปลงได้ซึ่งต้องใช้โปรแกรมเมอร์ในการพิจารณาการโคลนนิ่งและเธรดอย่างชัดเจน นอกจากนี้การขาดความปลอดภัยของเธรดใน DateTimeFormat ยังไม่เป็นที่รู้จักอย่างกว้างขวางและเป็นสาเหตุของปัญหาการเธรดที่ยากต่อการติดตาม
เช่นเดียวกับปัญหาเกี่ยวกับคลาสที่ Java SE มีสำหรับวันที่และเวลาก็ไม่มีคลาสสำหรับการสร้างโมเดลแนวคิดอื่น ๆ วันที่หรือเวลาที่ไม่ใช่โซนเวลาระยะเวลาช่วงเวลาและช่วงเวลาไม่มีการแสดงคลาสใน Java SE ด้วยเหตุนี้นักพัฒนาจึงมักใช้ int เพื่อแสดงระยะเวลาโดย javadoc ระบุหน่วย
การไม่มีแบบจำลองวันที่และเวลาที่ครอบคลุมยังส่งผลให้การดำเนินการทั่วไปหลายอย่างยุ่งยากกว่าที่ควรจะเป็น ตัวอย่างเช่นการคำนวณจำนวนวันระหว่างวันที่สองวันเป็นปัญหาหนักโดยเฉพาะในปัจจุบัน
JSR นี้จะแก้ไขปัญหาของรูปแบบวันที่และเวลาที่สมบูรณ์รวมถึงวันที่และเวลา (มีและไม่มีเขตเวลา) ระยะเวลาและช่วงเวลาช่วงเวลาการจัดรูปแบบและการแยกวิเคราะห์
getMonth()
is zero-based getYear()
คือ 1900-based (กล่าวคือปี 2009 แสดงเป็น 109)Date
ชั้นเรียนฉันรู้สึกแทนคุณ ... ในฐานะอดีตโปรแกรมเมอร์. NET ฉันถามคำถามเดียวกันเวลา API ใน. NET (ช่วงเวลา, การโอเวอร์โหลดตัวดำเนินการ) สะดวกมาก
ขั้นแรกในการสร้างวันที่ที่เฉพาะเจาะจงคุณใช้ API ที่เลิกใช้แล้วหรือ:
Calendar c = Calendar.getInstance();
c.set(2000, 31, 12)
เพื่อลบวันที่คุณทำสิ่งชั่วร้ายเช่น
Date firstDate = ...
Calendar c = Calendar.getInstance();
c.setTime(fistDate);
c.add(Calendar.DATE,-1);
Date dayAgo = c.getTime();
หรือแย่กว่านั้น
Date d = new Date();
Date d2 = new Date(d.getTime() - 1000*60*60*24);
หากต้องการทราบระยะเวลาที่ผ่านไประหว่างวันที่สองวัน (เป็นวัน / สัปดาห์ / เดือน) ... มันยิ่งแย่ลงไปอีก
อย่างไรก็ตามDateUtilsจาก apache ( org.apache.commons.lang.time.DateUtils
) มีวิธีการที่สะดวกและฉันพบว่าตัวเองใช้เฉพาะเมื่อเร็ว ๆ นี้
ดังที่ Brabster เขียน Joda Time ก็เป็นไลบรารีภายนอกที่ดีเช่นกัน แต่ apache ดูเหมือน "ธรรมดา" มากกว่าสิ่งอื่นใด ...
Period
และDuration
คลาสเพื่อคำนวณและแสดงเวลาที่ผ่านไปในระดับปี - เดือน - วันและชั่วโมง - นาที - วินาทีตามลำดับ
ฉันพบว่า Date API ของ Java ใช้งานได้จริง ปัญหาส่วนใหญ่ที่ผมเคยเห็นและได้ยินเกี่ยวกับความสัมพันธ์กับฟุ่มเฟื่อยจำเป็นที่จะต้องเกี่ยวข้องกับหลายชั้นเรียนที่จะทำอะไรที่เป็นประโยชน์ ( Calendar
, Date
, DateFormat
/ SimpleDateFormat
) และการขาดการ accessors getDayOfWeek()
ง่ายเช่น
Joda Timeเป็น API ทางเลือกที่ได้รับการยอมรับอย่างดีใน Java และในส่วน Why Joda Time จะให้ข้อโต้แย้งเพิ่มเติมว่าเหตุใดจึงเป็นทางเลือกที่ทำงานได้ซึ่งอาจเป็นที่สนใจ