Bekerja di waktu Java

Artikel ini membina maklumat yang disajikan dalam artikel Calculating Java Dates saya ( JavaWorld, 29 Disember 2000). Di sini saya telah menyenaraikan beberapa perkara penting dari artikel itu yang semestinya tidak asing bagi anda. Sekiranya perkara ini tidak jelas bagi anda, saya mengesyorkan agar anda membaca "Mengira Tarikh Java" untuk penjelasan lebih lanjut.

  1. Java memperhitungkan masa dalam milisaat sebelum atau selepas permulaan 1 Januari 1970.
  2. Pembina Datekelas Date()mengembalikan objek yang mewakili saat objek itu dibuat. Date's getTime()Cara mengembalikan longnilai yang nombor sama dengan jumlah milisaat sebelum atau selepas 1 Januari 1970.
  3. The DateFormatkelas digunakan untuk convert Dates kepada Strings, dan sebaliknya. getDateInstance()Kaedah statik mengembalikan DateFormatobjek dalam format lalai; yang getDateInstance(DateFormat.FIELD)mengembalikan DateFormatobjek dengan format yang ditetapkan. The format(Date d)Cara mengembalikan Stringyang mewakili tarikh, seperti "1 Januari 2002." Sebaliknya, parse(String s)kaedah mengembalikan Dateobjek berdasarkan tarikh yang Stringditunjukkan oleh argumen.
  4. Penampilan Strings yang dikembalikan dengan format()kaedah dapat bervariasi sesuai dengan pengaturan wilayah pada komputer tempat program dijalankan.
  5. The GregorianCalendarkelas mempunyai dua pengeluar penting: GregorianCalendar(), yang mengembalikan objek yang mewakili masa ini ia telah dicipta, dan GregorianCalendar(int year, int month, int date)pembina digunakan untuk membuat objek yang mewakili tarikh sewenang-wenangnya. Kaedah GregorianCalendarkelas getTime()mengembalikan Dateobjek. The add(int field, int amount)kaedah mengira tarikh dengan menambah atau menolak unit masa seperti hari, bulan atau tahun.

Kalendar dan masa Gregorian

Pembina dua GregorianCalendarkelas boleh digunakan untuk menangani masa. Yang pertama membuat objek yang mewakili tarikh, jam, dan minit:

Kalendar Gregorian (tahun int, bulan int, tarikh int, jam int, minit int) 

Yang kedua membuat objek yang mewakili tarikh, jam, minit, dan kedua:

Kalendar Gregorian (int tahun, int bulan, tarikh int, jam int, minit int, int kedua) 

Pertama, saya harus perhatikan bahawa setiap pembina memerlukan maklumat tarikh (tahun, bulan, dan hari) sebagai tambahan kepada maklumat masa. Sekiranya anda ingin bercakap mengenai jam 2:30 petang, anda mesti menentukan tarikhnya.

Juga, setiap GregorianCalendarpembina membuat objek yang mewakili momen dalam masa yang dikira dengan milisaat terdekat. Oleh itu, jika pembangun anda mengambil argumen hanya untuk tahun, bulan, dan tarikh, maka nilai untuk jam, minit, saat, dan milisaat ditetapkan menjadi sifar. Begitu juga, jika pembina anda mengambil argumen untuk tahun, bulan, tarikh, jam, dan minit, maka detik dan milisaat ditetapkan ke sifar.

TarikhFormat dan masa

Untuk membuat DateFormatobjek untuk memaparkan waktu dan tarikh, anda boleh menggunakan kaedah statik getDateTimeInstance(int dateStyle, int timeStyle). Kaedah itu menentukan gaya tarikh dan waktu yang ingin anda gunakan. Sekiranya anda berpuas hati dengan gaya lalai, anda boleh menggantikan yang lebih pendek getDateTimeInstance().

Untuk membuat DateFormatobjek untuk dipaparkan tepat pada waktunya, anda boleh menggunakan kaedah statik getTimeInstance(int timeStyle).

Program di bawah menunjukkan bagaimana kaedah getDateTimeInstance()dan getTimeInstance()kaedahnya berfungsi:

import java.util. *; import java.text. *; kelas awam Apollo {public static void main (String [] args) {GregorianCalendar liftOffApollo11 ​​= GregorianCalendar baru (1969, Kalendar.JULAI, 16, 9, 32); Tarikh d = liftOffApollo11.getTime (); DateFormat df1 = DateFormat.getDateTimeInstance (DateFormat.MEDIUM, DateFormat.MEDIUM); DateFormat df2 = DateFormat.getTimeInstance (DateFormat.SHORT); Rentetan s1 = df1.format (d); Rentetan s2 = df2.format (d); System.out.println (s1); System.out.println (s2); }}

Pada komputer saya, program di atas memaparkan perkara berikut:

16 Jul 1969 9:32:00 PG

9:32 PAGI

(Output dapat berubah-ubah sesuai dengan pengaturan wilayah komputer Anda.)

Mengira masa yang berlalu

Anda mungkin kadangkala perlu mengira masa yang berlalu; sebagai contoh, anda mungkin ingin mengetahui jangka masa proses pembuatan, memandangkan waktu permulaan dan akhir. Syarikat sewa yang menyewa barang mengikut jam atau hari mungkin juga berguna untuk mengira masa yang berlalu. Begitu juga, dalam dunia kewangan, sering kali diperlukan untuk mengira pembayaran faedah dalam jangka masa yang berlalu.

Untuk merumitkan masalah, manusia mengira masa yang berlalu sekurang-kurangnya dengan dua cara. Anda boleh mengatakan bahawa hari telah berlalu ketika 24 jam telah berlalu, atau apabila kalendar berubah dari satu hari ke hari berikutnya. Sekarang saya akan membincangkan dua cara berfikir itu.

Masa berlalu, kes 1: Unit penuh

Dalam kes ini, satu hari belum berlalu sehingga 24 jam berlalu, satu jam belum berlalu sehingga 60 minit berlalu, satu minit belum berlalu sehingga 60 saat berlalu, dan seterusnya. Dengan kaedah ini, 23 jam masa yang berlalu akan diterjemahkan menjadi sifar hari.

Untuk mengira masa berlalu dengan cara ini, anda mulakan dengan mengira milisaat yang berlalu. Untuk melakukannya, tukar setiap tarikh terlebih dahulu kepada bilangan milisaat sejak awal 1 Januari 1970. Anda kemudian tolak nilai milisaat pertama dari nilai milisaat kedua. Berikut adalah contoh pengiraan:

import java.util. *; kelas awam ElapsedMillis {public static void main (String [] args) {GregorianCalendar gc1 = GregorianCalendar baru (1995, 11, 1, 3, 2, 1); GregorianCalendar gc2 = GregorianCalendar baru (1995, 11, 1, 3, 2, 2); // dua tarikh di atas adalah satu saat terpisah Tarikh d1 = gc1.getTime (); Tarikh d2 = gc2.getTime (); panjang l1 = d1.getTime (); panjang l2 = d2.getTime (); perbezaan panjang = l2 - l1; System.out.println ("milisaat yang berlalu:" + perbezaan); }}

Program di atas mencetak yang berikut:

Milisaat yang berlalu: 1000

That program also causes some confusion. The GregorianCalendar class's getTime() returns a Date object, while the Date class's getTime() method returns a long number representing the milliseconds before or after the beginning of January 1, 1970. So even though the methods have the same name, their return types are different!

You can convert milliseconds to seconds using simple integer division, as in the following code fragment:

long milliseconds = 1999; long seconds = 1999 / 1000; 

That way of converting milliseconds to seconds eliminates fractions, so 1,999 milliseconds equals 1 second, while 2,000 milliseconds equals 2 seconds.

To calculate larger units -- such as days, hours, and minutes -- given a number of seconds, you can use the following process:

  1. Calculate the largest unit, reducing the number of seconds accordingly
  2. Calculate the next largest unit, reducing the number of seconds accordingly
  3. Repeat until only seconds remain

For example, if your elapsed time is 10,000 seconds, and you want to know how many hours, minutes, and seconds that value corresponds to, you start with the largest value: hours. Divide 10,000 by 3,600 (seconds in an hour) to calculate the number of hours. Using integer division, the answer is 2 hours (fractions are dropped in integer division). To calculate the remaining seconds, reduce 10,000 by 3,600 times 2 hours: 10,000 - (3,600 x 2) = 2,800 seconds. So you have 2 hours and 2,800 seconds.

Untuk menukar 2,800 saat ke minit, bahagikan 2,800 dengan 60 (saat seminit). Dengan pembahagian integer, jawapannya adalah 46. Dan 2,800 - (60 x 46) = 40 saat. Jawapan terakhir adalah 2 jam, 46 minit, dan 40 saat.

Pengiraan di atas ditunjukkan dalam program Java berikut:

import java.util. *; kelas awam Elapsed1 {public void calcHMS (int timeInSeconds) {int jam, minit, saat; jam = timeInSeconds / 3600; timeInSeconds = timeInSeconds - (jam * 3600); minit = timeInSeconds / 60; timeInSeconds = timeInSeconds - (minit * 60); saat = masaInSeconds; System.out.println (jam + "jam)" minit + "minit" + saat + "saat"); } utama kekosongan statik awam (String [] args) {Elapsed1 elap = baru Elapsed1 (); elap.calcHMS (10000); }}

Hasil daripada program di atas adalah:

2 jam 46 minit 40 saat

Program di atas mengira jumlah jam dengan betul, walaupun masa yang berlalu kurang dari satu jam. Sebagai contoh, jika anda menggunakan program di atas untuk mengira 1,000 saat, outputnya adalah:

0 jam 16 minit 40 saat

Untuk menunjukkan contoh dunia nyata, program berikut mengira masa berlalu berdasarkan penerbangan Apollo 11 ke bulan:

import java.util.*; public class LunarLanding { public long getElapsedSeconds(GregorianCalendar gc1, GregorianCalendar gc2) { Date d1 = gc1.getTime(); Date d2 = gc2.getTime(); long l1 = d1.getTime(); long l2 = d2.getTime(); long difference = Math.abs(l2 - l1); return difference / 1000; } public void calcHM(long timeInSeconds) { long hours, minutes, seconds; hours = timeInSeconds / 3600; timeInSeconds = timeInSeconds - (hours * 3600); minutes = timeInSeconds / 60; System.out.println(hours + " hour(s) " + minutes + " minute(s)" ); } public static void main(String[] args) { GregorianCalendar lunarLanding = new GregorianCalendar(1969, Calendar.JULY, 20, 16, 17); GregorianCalendar lunarDeparture = new GregorianCalendar(1969, Calendar.JULY, 21, 13, 54); GregorianCalendar startEVA = new GregorianCalendar(1969, Calendar.JULY, 20, 22, 56); GregorianCalendar endEVA = new GregorianCalendar(1969, Calendar.JULY, 21, 1, 9); LunarLanding apollo = new LunarLanding(); long eva = apollo.getElapsedSeconds(startEVA, endEVA); System.out.print("EVA duration = "); apollo.calcHM(eva); long lunarStay = apollo.getElapsedSeconds(lunarLanding, lunarDeparture); System.out.print("Lunar stay = "); apollo.calcHM(lunarStay); } } 

Output from the above program is:

EVA duration = 2 hour(s) 13 minute(s)

Lunar stay = 21 hour(s) 37 minute(s)

So far, I have made calculations based on simple formulas like: "1 minute = 60 seconds," "1 hour = 60 minutes," and "1 day = 24 hours."

What about "1 month = ? days" and "1 year = ? days"?

Months can consist of 28, 29, 30, or 31 days; years can be 365 or 366 days. Therefore, problems arise when you try to calculate full units of time for months and years. For example, if you use the average number of days in a month (approximately 30.4375), and you calculate the number of elapsed months based on the following two intervals:

  • July 1, 2:00 a.m. to July 31, 10:00 p.m.
  • February 1, 2:00 a.m. to February 29, 10:00 p.m.

the first calculation will result in 1 month; the second will result in zero months!

So, think very carefully before you calculate elapsed time in full units for months and years.

Elapsed time, case 2: Time unit change

The definition of time unit change is relatively simple: If you are counting days, you simply count the number of times the date has changed. For example, if something starts on the 15th and ends on the 17th, 2 days have passed. (The date changed first to the 16th, then to the 17th.) Similarly, if a process starts at 3:25 in the afternoon and finishes at 4:10 p.m., 1 hour has passed because the hour has changed once (from 3 to 4).

Libraries often calculate time in this manner. For example, if I borrow a book from my library, I don't need to have the book in my possession for a minimum of 24 hours for the library to consider it borrowed for one day. Instead, the day that I borrow the book is recorded on my account. As soon as the date switches to the next day, I have borrowed the book for one day, even though the amount of time is often less than 24 hours.

When calculating elapsed time in the sense of time unit change, it doesn't usually make sense to calculate more than one unit of time. For example, if I borrow a library book at 9:00 p.m., and return it the next day at noon, I can calculate that I've borrowed the book for one day. However, there is little sense in asking, "One day and how many hours?" Since the book was loaned for a total of 15 hours, is the answer one day and negative nine hours? Therefore, for this tutorial, I will calculate time unit change for only one unit of time.

Algorithm for calculating time unit of change

This is how you calculate time unit of change between two dates:

  1. Make copies of the two dates. The clone() method can make copies for you.
  2. Dengan menggunakan salinan tarikh, tetapkan semua medan yang lebih kecil daripada unit perubahan ke nilai minimum setiap medan. Contohnya, jika anda mengira hari yang berlalu, tetapkan jam, minit, saat dan milisaat menjadi sifar. Dalam kes ini, gunakan clear()kaedah untuk menetapkan medan masa ke nilai terendah.
  3. Ambil tarikh lebih awal dan tambahkan satu ke medan yang anda hitung, ulangi sehingga kedua tarikh sama. Berapa kali anda menambahkannya adalah jawapannya. Anda boleh menggunakan before()dan after()kaedah, yang mengembalikan nilai boolean, untuk menguji sama ada satu tarikh sebelum atau selepas tarikh lain.

Kelas berikut mempunyai kaedah untuk menghitung hari dan bulan.