CodeGym /Blog Java /Ngẫu nhiên /Làm thế nào để không bị mất thời gian: Ngày giờ và Lịch

Làm thế nào để không bị mất thời gian: Ngày giờ và Lịch

Xuất bản trong nhóm
CHÀO! Hôm nay chúng ta sẽ bắt đầu làm việc với một kiểu dữ liệu mới mà chúng ta chưa từng gặp trước đây, cụ thể là ngày tháng. Làm thế nào để không bị mất thời gian: DateTime và Lịch - 1Tôi không nghĩ mình cần phải giải thích ngày tháng là gì. :) Về nguyên tắc, chúng ta có thể lưu trữ ngày và giờ hiện tại trong một Chuỗi Java thông thường.

public class Main {
   public static void main(String[] args) {

       String date = "June 11, 2018";
       System.out.println(date);
   }
}
Nhưng phương pháp này có nhiều nhược điểm. Lớp này Stringđược thiết kế để làm việc với văn bản và các phương thức của nó phù hợp với nhiệm vụ này. Nếu chúng ta cần thao tác một ngày theo một cách nào đó (ví dụ: thêm 2 giờ), Stringsẽ không hoạt động tốt. Hoặc nếu chúng ta muốn hiển thị ngày giờ hiện tại khi chương trình được biên dịch. Stringcũng không giúp được gì ở đây: vào thời điểm bạn viết mã và chạy nó, thời gian sẽ thay đổi và bảng điều khiển sẽ hiển thị thông tin sai. Đó là lý do tại sao những người tạo ra Java đã cung cấp một số lớp để làm việc với ngày tháng và thời gian. Đầu tiên trong số này làjava.util.Date

lớp ngày

Chúng tôi đã chỉ định tên đầy đủ của nó, bởi vì một gói Java khác có lớp java.sql.Date. Đừng trộn chúng lên! Điều đầu tiên bạn cần biết về nó là nó lưu trữ ngày tháng dưới dạng số mili giây đã trôi qua kể từ ngày 1 tháng 1 năm 1970. Hệ thống thời gian này thậm chí còn có tên riêng: " Unix-time " Một cách tiếp cận khá thú vị, sẽ không bạn có đồng ý không? :) Điều đáng nhớ thứ hai là: Nếu bạn tạo một Dateđối tượng bằng cách sử dụng hàm tạo mặc định, kết quả sẽ biểu thị ngày và giờ hiện tại tại thời điểm đối tượng được tạo . Hãy nhớ rằng chúng tôi đã nói rằng một ngày được biểu thị bằng a Stringsẽ gặp khó khăn với một nhiệm vụ như vậy? Lớp Datexử lý nó một cách dễ dàng.

public class Main {
   public static void main(String[] args) {

       Date date = new Date();
       System.out.println(date);
   }
}
Chạy mã này nhiều lần và bạn sẽ thấy thời gian thay đổi liên tục. :) Điều này khả thi vì thời gian được lưu trữ dưới dạng mili giây: chúng là đơn vị thời gian cực nhỏ nên kết quả có độ chính xác cao. Lớp Datenày có một hàm tạo khác: bạn có thể chuyển số mili giây chính xác kể từ 00:00 ngày 1 tháng 1 năm 1970 đến ngày được yêu cầu và một đối tượng ngày tương ứng sẽ được tạo:

public class Main {
   public static void main(String[] args) {

       Date date = new Date(1212121212121L);
       System.out.println(date);
   }
}
Đầu ra bảng điều khiển: Thứ sáu ngày 30 tháng 5 04:20:12 GMT 2008 Chúng tôi nhận được ngày 30 tháng 5 năm 2008. "Thứ sáu" cho biết ngày trong tuần (Thứ sáu, duh) và GMT là múi giờ (Giờ chuẩn Greenwich). Một phần nghìn giây được chuyển thành longs, vì số mili giây thường không khớp với một phần tử int. Vì vậy, chúng ta có thể cần thực hiện những thao tác nào với ngày tháng? Tất nhiên, rõ ràng nhất là so sánh . Để xác định xem một ngày đến trước hay sau ngày khác. Điều này có thể được thực hiện theo nhiều cách. Ví dụ: bạn có thể gọi Date.getTime()phương thức, phương thức này trả về số mili giây đã trôi qua kể từ nửa đêm ngày 1 tháng 1 năm 1970. Chỉ cần gọi phương thức này trên hai đối tượng Date và so sánh kết quả:

public class Main {
   public static void main(String[] args) {

       Date date1 = new Date();

       Date date2 = new Date();

       System.out.println((date1.getTime() > date2.getTime())?
               "date1 is later than date2" : "date1 is earlier than date2");
   }
}
Kết quả: date1 sớm hơn date2 Nhưng cũng có một cách thuận tiện hơn, tức là bằng cách sử dụng các phương thức đặc biệt do lớp Date cung cấp: before()và . Tất cả chúng đều trả về một giá trị boolean. Phương thức kiểm tra xem ngày của chúng ta có sớm hơn ngày được truyền dưới dạng đối số hay không: after()equals()before()

public class Main {
   public static void main(String[] args) throws InterruptedException {

       Date date1 = new Date();

       Thread.sleep(2000);// Suspend the program for 2 seconds
       Date date2 = new Date();

       System.out.println(date1.before(date2));
   }
}
Đầu ra của bàn điều khiển: true Tương tự như vậy, after()phương thức kiểm tra xem liệu ngày của chúng ta có muộn hơn ngày được truyền dưới dạng đối số hay không:

public class Main {
   public static void main(String[] args) throws InterruptedException {

       Date date1 = new Date();

       Thread.sleep(2000);// Suspend the program for 2 seconds
       Date date2 = new Date();

       System.out.println(date1.after(date2));
   }
}
Đầu ra của bảng điều khiển: sai Trong các ví dụ của chúng tôi, chúng tôi "đặt chương trình vào chế độ ngủ" trong 2 giây để hai ngày được đảm bảo khác nhau. Trên các máy tính nhanh, thời gian giữa việc tạo date1date2có thể nhỏ hơn một phần nghìn giây, khiến cả hai before()after()trả về giá trị sai. Nhưng trong trường hợp này, equals()phương thức sẽ trả về true! Rốt cuộc, nó so sánh số mili giây kể từ 00:00 ngày 1 tháng 1 năm 1970 cho mỗi ngày. Các đối tượng chỉ được coi là bằng nhau nếu chúng khớp với mili giây :

public static void main(String[] args) {

   Date date1 = new Date();
   Date date2 = new Date();

   System.out.println(date1.getTime());
   System.out.println(date2.getTime());

   System.out.println(date1.equals(date2));
}
Đây là một điều khác bạn cần chú ý. Nếu bạn mở tài liệu về Datelớp này trên trang web của Oracle , bạn sẽ thấy rằng nhiều phương thức và hàm tạo của nó đã được đánh dấu là Không dùng nữa (nghĩa là không được khuyến nghị sử dụng). Đây là những gì những người tạo ra Java nói về các phần của lớp không được dùng nữa:
"Phần tử chương trình được chú thích @Deprecated là thứ mà các lập trình viên không được khuyến nghị sử dụng, thường là vì nó nguy hiểm hoặc vì có giải pháp thay thế tốt hơn."
Điều này không có nghĩa là những phương pháp này hoàn toàn không thể sử dụng được. Nếu bạn cố chạy mã bằng các phương thức không dùng nữa trong IDE, rất có thể nó sẽ hoạt động. Ví dụ: hãy xem xét phương thức không dùng nữa Date.getHours(), phương thức này trả về số giờ được liên kết với một Dateđối tượng.

public static void main(String[] args) {

   Date date1 = new Date();

   System.out.println(date1.getHours());
}
Nếu bạn bắt đầu mã lúc 14:21 (2:21 chiều), nó sẽ hiển thị số 14. Như bạn có thể thấy, phương thức không dùng nữa bị gạch bỏ, nhưng nó vẫn hoạt động. Các phương pháp này không bị xóa để không phá vỡ phần lớn mã hiện có sử dụng chúng. Nói cách khác, các phương thức này không bị "hỏng" cũng không bị "xóa". Chúng chỉ đơn giản là không được khuyến nghị sử dụng vì có sẵn một giải pháp thay thế thuận tiện hơn. Ngẫu nhiên, tài liệu đề cập cụ thể đến sự thay thế này:
Làm thế nào để không bị mất thời gian: DateTime và Lịch - 2
Hầu hết Datecác phương thức của lớp đã được chuyển sang Calendarlớp cải tiến và mở rộng. Tiếp theo chúng ta sẽ làm quen với lớp học đó. :)

lớp lịch

JDK 1.1 đã giới thiệu một lớp mới: Calendar. Nó giúp làm việc với ngày tháng trong Java dễ dàng hơn một chút so với trước đây. Việc triển khai duy nhất của lớp Calendarmà chúng ta sẽ làm việc là GregorianCalendarlớp. Nó thực hiện lịch Gregorian, được hầu hết các quốc gia trên thế giới quan sát. Ưu điểm chính của nó là nó có thể hoạt động với ngày ở định dạng thuận tiện hơn. Ví dụ: nó có thể:
  • Thêm một tháng hoặc ngày vào ngày hiện tại
  • Kiểm tra xem năm đó có phải là năm nhuận hay không;
  • Trả về các thành phần riêng lẻ của ngày (ví dụ: trích xuất số tháng từ toàn bộ ngày)
  • Nó cũng chứa một hệ thống các hằng số rất thuận tiện (nhiều trong số đó chúng ta sẽ thấy bên dưới).
Một cải tiến quan trọng khác của Calendarlớp là hằng số Lịch.ERA của nó : bạn có thể chỉ ra một ngày trước kỷ nguyên chung (TCN - trước Công nguyên) hoặc trong kỷ nguyên chung (sau Công nguyên - Anno Domini). Hãy xem xét tất cả điều này với các ví dụ. Hãy tạo một calendarđối tượng với ngày 25 tháng 1 năm 2017:

public static void main(String[] args) {

  Calendar calendar = new GregorianCalendar(2017, 0 , 25);
}
Trong Calendarlớp (cũng như Datelớp cho vấn đề đó), tháng bắt đầu từ số 0 , vì vậy chúng tôi chuyển số 0 làm đối số thứ hai. Khi làm việc với Calendarlớp học, điều quan trọng là phải hiểu rằng đây chỉ là một lịch chứ không phải một ngày riêng lẻ. Làm thế nào để không bị mất thời gian: DateTime và Lịch - 3 Một ngày chỉ là một vài con số biểu thị một khoảng thời gian cụ thể. Lịch là toàn bộ hệ thống cho phép bạn làm nhiều việc với ngày tháng. :) Điều này rất rõ ràng nếu bạn cố gắng hiển thị Calendarđối tượng: Đầu ra: java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/London",offset=0,dstSavings=0,useDaylight= false,transitions=79,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=1,ERA=?,YEAR=2017,MONTH=0,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=25,DAY_OF_YEAR=?,DAY_OF_WEEK=? ,DAY_OF_WEEK_IN_MONTH=?,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?] Xem lượng thông tin bạn nhận được! Lịch có một loạt các thuộc tính mà một ngày bình thường không có và tất cả chúng đều được hiển thị (đây là cách phươngtoString()thức hoạt động trongCalendarlớp). Nếu bạn chỉ cần lấy một ngày đơn giản từ lịch, tức là mộtDateđối tượng, hãy sử dụngCalendar.getTime()phương pháp (tên không hợp lý nhất, nhưng bạn có thể làm gì?):

public static void main(String[] args) {

   Calendar calendar = new GregorianCalendar(2017, 0 , 25);
   Date date = calendar.getTime();
   System.out.println(date);
}
Dữ liệu ra: Thứ tư ngày 25 tháng 1 00:00:00 GMT 2017 Bây giờ chúng tôi đã lấy lịch và "thu nhỏ nó" thành một ngày bình thường. Hãy đi xa hơn nữa. Ngoài việc chỉ định các tháng theo số của chúng, bạn có thể sử dụng các giá trị trường hằng sốCalendar của lớp . Các hằng số này là các trường tĩnh của lớp có giá trị đặt trước không thể thay đổi. Đây thực sự là một lựa chọn thậm chí còn tốt hơn, vì sử dụng chúng sẽ cải thiện khả năng đọc mã của bạn. Calendar

public static void main(String[] args) {
   GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
}
Calendar.JANUARY là một trong những hằng số đại diện cho các tháng trong năm. Ví dụ, sử dụng các hằng số được đặt tên này, sẽ không ai quên rằng số 3 có nghĩa là tháng 4 chứ không phải tháng thứ ba mà chúng ta muốn gọi là tháng 3. Chỉ cần viết Calendar.APRIL và bạn đã hoàn tất. :) Tất cả các trường lịch (số, tháng, phút, giây, v.v.) có thể được chỉ định riêng bằngset()phương pháp này. Phương pháp này rất thuận tiện, bởi vìCalendarlớp có một hằng số cho từng trường và mã kết quả rất dễ đọc. Trong ví dụ trước, chúng tôi đã tạo một ngày nhưng không đặt thời gian cho ngày đó. Hãy đặt thời gian 19:42:12

public static void main(String[] args) {
   Calendar calendar = new GregorianCalendar();
   calendar.set(Calendar.YEAR, 2017);
   calendar.set(Calendar.MONTH, 0);
   calendar.set(Calendar.DAY_OF_MONTH, 25);
   calendar.set(Calendar.HOUR_OF_DAY, 19);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   System.out.println(calendar.getTime());
}
Đầu ra: Thứ tư ngày 25 tháng 1 19:42:12 GMT 2017 Chúng tôi gọi set()phương thức, chuyển một hằng số (tùy thuộc vào trường mà chúng tôi muốn thay đổi) và giá trị mới cho trường. Hóa ra set()phương pháp này là một loại "siêu thiết lập" biết cách đặt giá trị không chỉ cho một trường mà cho nhiều trường. :) CalendarLớp sử dụng add()phương pháp cộng trừ giá trị. Bạn chuyển vào trường bạn muốn thay đổi và một số (chính xác là số tiền bạn muốn cộng/trừ khỏi giá trị hiện tại). Ví dụ: hãy lấy một ngày là 2 tháng trước ngày chúng tôi đã tạo:

public static void main(String[] args) {
   Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 19);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   calendar.add(Calendar.MONTH, -2); // To subtract, pass a negative number
   System.out.println(calendar.getTime());
}
Kết quả: Thứ Sáu, 25/11 19:42:12 GMT 2016 Rất tốt! Chúng tôi đã có ngày 2 tháng trước. Điều này không chỉ khiến tháng thay đổi: năm cũng thay đổi từ 2017 thành 2016. Tất nhiên, khi chuyển đổi ngày, năm hiện tại được tính tự động mà bạn không cần phải theo dõi thủ công. Nhưng nếu vì lý do nào đó bạn cần tắt hành vi này, bạn có thể làm như vậy. Phương thức này roll()có thể cộng và trừ các giá trị mà không ảnh hưởng đến các giá trị còn lại . Ví dụ, như thế này:

public static void main(String[] args) {
   Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 10);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   calendar.roll(Calendar.MONTH, -2);
   System.out.println(calendar.getTime());
}
Chúng tôi đã làm chính xác điều tương tự như trong ví dụ trước: chúng tôi mất 2 tháng kể từ ngày hiện tại. Nhưng bây giờ mã này làm một việc khác: tháng đã thay đổi từ tháng 1 sang tháng 11, nhưng năm vẫn không thay đổi—2017! Đầu ra: Sat 25 tháng 11 10:42:12 GMT 2017 Di chuyển dọc. Như chúng tôi đã nói ở trên, chúng tôi có thể lấy tất cả Calendarcác trường một cách riêng biệt. Chúng tôi làm điều này với get()phương pháp:

public static void main(String[] args) {
   GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 10);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   System.out.println("Year: " + calendar.get(Calendar.YEAR));
   System.out.println("Month: " + calendar.get(Calendar.MONTH));
   System.out.println("Week in the month: " + calendar.get(Calendar.WEEK_OF_MONTH));// Week in this month?

   System.out.println("Day: " + calendar.get(Calendar.DAY_OF_MONTH));

   System.out.println("Hours: " + calendar.get(Calendar.HOUR));
   System.out.println("Minutes: " + calendar.get(Calendar.MINUTE));
   System.out.println("Seconds: " + calendar.get(Calendar.SECOND));
   System.out.println("Milliseconds: " + calendar.get(Calendar.MILLISECOND));

}
Đầu ra: Năm: 2017 Tháng: 0 Tuần trong tháng: 5 Ngày: 25 Giờ: 10 Phút: 42 Giây: 12 Phần nghìn giây: 0 Vì vậy, ngoài "siêu lập trình" của lớp, còn có một Calendar"siêu lập trình viên" “. :) Tất nhiên, một khía cạnh thú vị khác của lớp học này là làm việc với các thời đại. Để tạo ngày "BC", bạn cần sử dụng trường Calendar.ERA. Ví dụ: hãy tạo ngày cho Trận chiến Cannae, nơi Hannibal đánh bại quân đội La Mã. Điều này xảy ra vào ngày 2 tháng 8 năm 216 trước Công nguyên:

public static void main(String[] args) {
   GregorianCalendar cannae = new GregorianCalendar(216, Calendar.AUGUST, 2);
   cannae.set(Calendar.ERA, GregorianCalendar.BC);

   DateFormat df = new SimpleDateFormat("MMM dd, yyy GG");
   System.out.println(df.format(cannae.getTime()));
}
Ở đây, chúng tôi đã sử dụng SimpleDateFormatlớp để in ngày ở định dạng dễ hiểu hơn đối với chúng tôi (các chữ cái "GG" cho biết chúng tôi muốn thời đại được hiển thị). Đầu ra: Ngày 02 tháng 8 năm 216 trước Công nguyên. Lớp Calendarcó nhiều phương thức và hằng số hơn. Bạn có thể đọc về chúng trong tài liệu . Nếu không thích định dạng ngày này Thứ bảy ngày 25 tháng 11 10:42:12 GMT 2017 thì bạn có thể sử dụng SimpleDateFormatđể dễ dàng biến nó thành những gì bạn muốn.

public static void main(String[] args) {

   SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE, MMMM d, yyyy");
   Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 10);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   calendar.roll(Calendar.MONTH, -2);
   System.out.println(dateFormat.format(calendar.getTime()));
}
Đầu ra: Thứ bảy, ngày 25 tháng 11 năm 2017 Tốt hơn nhiều phải không? :)
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION