Работа в Java време

Тази статия се основава на информацията, представена в статията ми за изчисляване на датите на Java ( JavaWorld, 29 декември 2000 г.). Тук изброих някои ключови моменти от тази статия, които трябва да са ви познати. Ако тези точки не са ви ясни, препоръчвам ви да прочетете "Изчисляване на дати на Java" за допълнително обяснение.

  1. Java отчита времето в милисекунди преди или след началото на 1 януари 1970 г.
  2. Конструкторът на Dateкласа Date()връща обект, който представлява момента на създаване на обекта. Dateе getTime()метод връща longстойност, чийто брой е равен на броя на милисекунди преди или след 1 януари 1970 година.
  3. В DateFormatклас се използва за конвертиране Dateи да Stringе, и обратно. Статичният getDateInstance()метод връща DateFormatобект във формат по подразбиране; на getDateInstance(DateFormat.FIELD)Връща DateFormatобект с определен формат. В format(Date d)метода връща String, който представлява датата, като "1 януари 2002 г." Обратно, parse(String s)методът връща Dateобект въз основа на датата, която Stringаргументът представлява.
  4. Появата на Strings, върнати от format()метода, може да варира в зависимост от регионалните настройки на компютъра, на който се изпълнява програмата.
  5. В GregorianCalendarкласа има две важни конструктори: GregorianCalendar(), която връща обект, който представлява в момента той е създаден, а GregorianCalendar(int year, int month, int date)конструктора използва за създаване на един обект, който представлява произволна дата. Методът на GregorianCalendarкласа getTime()връща Dateобект. В add(int field, int amount)метода изчислява датите чрез добавяне или изваждане на единици за време, като дни, месеци или години.

Григориански календар и време

GregorianCalendarКонструктори от два класа могат да се използват за справяне с времето. Първият създава обект, който представлява дата, час и минута:

GregorianCalendar (int година, int месец, int дата, int час, int минута) 

Втората създава обект, който представлява дата, час, минута и секунда:

GregorianCalendar (int година, int месец, int дата, int час, int минута, int секунда) 

Първо, трябва да отбележа, че всеки конструктор изисква информация за дата (година, месец и ден) в допълнение към информация за времето. Ако искате да говорите около 14:30, трябва да посочите датата.

Също така всеки GregorianCalendarконструктор създава обект, който представлява момент във времето, изчислен с точност до милисекунда. По този начин, ако вашият конструктор взема аргументи само за годината, месеца и датата, тогава стойностите за часове, минути, секунди и милисекунди са зададени на нула. По същия начин, ако вашият конструктор взема аргументи за година, месец, дата, часове и минути, тогава секундите и милисекундите са зададени на нула.

DateFormat и час

За да създадете DateFormatобект за показване на час и дата, можете да използвате статичния метод getDateTimeInstance(int dateStyle, int timeStyle). Този метод определя стиловете за дата и час, които искате да използвате. Ако сте доволни от стиловете по подразбиране, можете да замените по-краткия getDateTimeInstance().

За да създадете DateFormatобект, който да показва само времето, можете да използвате статичния метод getTimeInstance(int timeStyle).

Програмата по-долу показва как работят методите getDateTimeInstance()и getTimeInstance():

импортиране на java.util. *; импортиране на java.text. *; публичен клас Apollo {публична статична празнота main (String [] args) {GregorianCalendar liftOffApollo11 ​​= new GregorianCalendar (1969, Calendar.ЮЛИ, 16, 9, 32); Дата d = liftOffApollo11.getTime (); DateFormat df1 = DateFormat.getDateTimeInstance (DateFormat.MEDIUM, DateFormat.MEDIUM); DateFormat df2 = DateFormat.getTimeInstance (DateFormat.SHORT); Низ s1 = df1.format (d); Низ s2 = df2.format (d); System.out.println (s1); System.out.println (s2); }}

На моя компютър горната програма показва следното:

16 юли 1969 г. 9:32:00

9:32 ч

(Изходът може да варира в зависимост от регионалните настройки на вашия компютър.)

Изчисляване на изминалото време

Понякога може да се наложи да изчислите изминалото време; например, може да искате да знаете продължителността на производствения процес, като се имат предвид началното и крайното време. Фирма под наем, която дава под наем артикули по час или ден, също може да намери за полезно да изчисли изминалото време. По подобен начин във финансовия свят често е необходимо да се изчисляват лихвените плащания през изминалото време.

За да усложни проблема, хората изчисляват изминалото време поне по два начина. Можете да кажете, че е изминал ден, когато са изминали 24 часа, или когато календарът се променя от един ден на следващия. Сега ще обсъдя тези два начина на мислене.

Изминало време, случай 1: Пълни единици

В този случай ден не е изминал, докато не са изминали 24 часа, час не е изминал, докато не са изминали 60 минути, минута не е изминала, докато не са изминали 60 секунди и т.н. При този метод 23 часа изминало време биха се превърнали в нула дни.

За да изчислите изминалото време по този начин, започвате с изчисляване на изминалите милисекунди. За целта първо преобразувайте всяка дата в броя на милисекундите от началото на 1 януари 1970 г. След това изваждате първата милисекунда от втората милисекунда. Ето примерно изчисление:

импортиране на java.util. *; публичен клас ElapsedMillis {публична статична празнота main (String [] args) {GregorianCalendar gc1 = new GregorianCalendar (1995, 11, 1, 3, 2, 1); GregorianCalendar gc2 = нов GregorianCalendar (1995, 11, 1, 3, 2, 2); // горните две дати се разделят на една секунда Дата d1 = gc1.getTime (); Дата d2 = gc2.getTime (); дълго l1 = d1.getTime (); дълго l2 = d2.getTime (); дълга разлика = l2 - l1; System.out.println ("Изминали милисекунди:" + разлика); }}

Горната програма отпечатва следното:

Изминали милисекунди: 1000

Тази програма също създава известно объркване. В GregorianCalendarкласа на getTime()възвръщаемост на Dateобектите, а Dateкласът е getTime()метод връща longчисло, представляващо милисекунди преди или след началото на 1 януари 1970 г. Така че, въпреки че методите имат едно и също име, типа им за връщане са различни!

Можете да конвертирате милисекунди в секунди, като използвате просто целочислено разделение, както в следния фрагмент на кода:

дълги милисекунди = 1999; дълги секунди = 1999/1000;

По този начин преобразуването на милисекунди в секунди елиминира фракциите, така че 1 999 милисекунди се равнява на 1 секунда, докато 2000 милисекунди са равни на 2 секунди.

За да изчислите по-големи единици - като дни, часове и минути - при определен брой секунди, можете да използвате следния процес:

  1. Изчислете най-голямата единица, като съответно намалите броя на секундите
  2. Изчислете следващата най-голяма единица, като съответно намалите броя на секундите
  3. Повторете, докато останат само секунди

Например, ако изминалото ви време е 10 000 секунди и искате да знаете на колко часа, минути и секунди съответства тази стойност, започвате с най-голямата стойност: часа. Разделете 10 000 на 3600 (секунди в час), за да изчислите броя на часовете. Използвайки целочислено деление, отговорът е 2 часа (фракциите се изпускат при целочислено деление). За да изчислите оставащите секунди, намалете 10 000 на 3 600 по 2 часа: 10 000 - (3 600 х 2) = 2 800 секунди. Така че имате 2 часа и 2800 секунди.

За да превърнете 2800 секунди в минути, разделете 2800 на 60 (секунди в минута). При целочислено деление отговорът е 46. И 2800 - (60 х 46) = 40 секунди. Крайният отговор е 2 часа, 46 минути и 40 секунди.

Горното изчисление е показано в следната Java програма:

импортиране на java.util. *; публичен клас Elapsed1 {public void calcHMS (int timeInSeconds) {int часа, минути, секунди; часа = timeInSeconds / 3600; timeInSeconds = timeInSeconds - (часа * 3600); минути = timeInSeconds / 60; timeInSeconds = timeInSeconds - (минути * 60); секунди = timeInSeconds; System.out.println (часове + "час (и)" + минути + "минути (и)" + секунди + "секунда (и)"); } public static void main (String [] args) {Elapsed1 elap = нов Elapsed1 (); elap.calcHMS (10000); }}

Резултатът от горната програма е:

2 часа (и) 46 минути (и) 40 секунда (и)

Горната програма изчислява броя часове правилно, дори когато изминалото време е по-малко от час. Например, ако използвате горната програма за изчисляване на 1000 секунди, изходът е:

0 час (а) 16 минута (и) 40 секунда (и)

За да покаже пример от реалния свят, следната програма изчислява изминалото време въз основа на полета на Аполо 11 до Луната:

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. Използвайки копията на датите, задайте всички полета, които са по-малки от единицата за промяна, на минималната стойност на всяко поле. Например, ако броите изминалите дни, задайте нула на часове, минути, секунди и милисекунди. В този случай използвайте clear()метода, за да зададете полетата за време на най-ниската им стойност.
  3. Вземете по-ранната дата и добавете една към полето, което броите, като повтаряте, докато двете дати са равни. Броят на добавянията на един е отговорът. Можете да използвате before()и after()методите, които се връщат булева стойност, за да определят дали един е преди или след друга дата.

Следващият клас има методи за броене на дни и месеци.