С момента выпуска Java 8 в 14 году наш древний java.util.Date, наконец, не единственный вариант для управления датой и временем в Java.
На самом деле, API, связанный с датой и временем в Java, всегда подвергался критике со стороны мира не только потому, что его дизайн и разделение труда неясны, часто класс может обрабатывать и дату, и время, что очень запутанно, но и из-за числового отображения определенных лет, месяцев и дат Store Anti-Human, например: 0 соответствует месяцу январь, 11 соответствует месяцу декабрь, 118 соответствует 2018 году (1900 + 118) и т. д.
Часто, когда мы получаем определенное значение года-месяца, нам все еще нужно выполнить соответствующие операции, чтобы получить точную информацию о годе-месяце-дне.До нашей Java 8 мы перепроектировали API даты и времени, опираясь на превосходный дизайн третьего- сторонняя библиотека с открытым исходным кодом Joda-Time., по сравнению с предыдущей, можно сказать, что она стала в сто раз проще в использовании, а все связанные API-интерфейсы находятся в пакете java.time.
древний интерфейс даты и времени
Дата, представляющая информацию о времени
Все компьютеры в мире хранят время внутри себя, используя целое число типа long, и значение этого целого числа равно количеству миллисекунд относительно GMT (1 января 1970 г., 0:00:00). Например:
public static void main(String[] args){
//January 1, 1970 00:00:00 GMT.
Date date = new Date(1000);
System.out.println(date);
}
Выходной результат:
//1970-1-1 8:00:01
Thu Jan 01 08:00:01 CST 1970
Многие люди могут задаться вопросом, 1000 означает 1 секунду от стандартного времени, так почему же время ушло на восемь часов больше?
Это связано с «часовым поясом».Если вы находитесь в районе Гринвича Соединенного Королевства, результаты будут такими, как ожидалось, но мы находимся в восточно-восьмом округе Китая, и время составляет восемь часов. ранее, поэтому разные часовые пояса основаны на разных базовых значениях.
Класс Date действительно играл много ролей в прошлом.Из его исходного кода видно, что существуют методы, которые могут манипулировать временем, методы, которые могут манипулировать годом, месяцем и датой, и даже он может управлять часовой пояс. Можно сказать, что для связанных операций с датой и временем достаточно одного человека.
Но мир такой. У вас слишком много вещей, которыми нужно управлять, и, естественно, вы не можете охватить все. Дизайн многих методов в Date не очень разумен. Как мы уже говорили, он даже немного античеловеческий. Итак, почти 80% методов класса Date теперь устарели и помечены как @Deprecated.
Текущее позиционирование Sun для Date:уникально представить момент, поэтому его внутренности должны вращаться вокруг этой целой миллисекунды и больше не сосредотачиваться на такой информации, как различные часовые пояса альманаха.
Date позволяет создавать экземпляр объекта с помощью следующих двух конструкторов:
private transient long fastTime;
public Date() {
this(System.currentTimeMillis());
}
public Date(long date) {
fastTime = date;
}
Свойство fastTime здесь хранит миллисекунды, соответствующие моменту. Два конструктора по-прежнему очень просты. Если вызывается конструктор без аргументов, виртуальная машина назначит fastTime с текущим значением момента системы.
Есть несколько других методов, которые не устарены:
- Публичное долгое время получить (): возвращает количество миллисекунд, хранящихся внутри
- public void setTime(long time): количество миллисекунд для сброса памяти
- public boolean before(Date when): сравнивает, является ли данный момент более ранним, чем текущий экземпляр Date
- public boolean after(Date when): сравнивает, является ли данный момент более поздним, чем текущий экземпляр Date
Также после jdk1.8 добавлены два метода для преобразования новых интерфейсов в Java 8, которые будут представлены позже.
Календарь с описанием годового календаря
Календарь используется для представления информации о дате, такой как год, месяц, день и т. д. Это абстрактный класс, поэтому его объекты-экземпляры обычно получают с помощью следующих четырех фабричных методов.
public static Calendar getInstance()
public static Calendar getInstance(TimeZone zone)
public static Calendar getInstance(Locale aLocale)
public static Calendar getInstance(TimeZone zone,Locale aLocale)
Фактически, внутренний метод в конечном итоге вызовет тот же самый внутренний метод:
private static Calendar createCalendar(TimeZone zone,Locale aLocale)
Для этого метода требуются два параметра: один — часовой пояс, другой — страна и язык, то есть для создания экземпляра календаря требуется как минимум информация об этих двух параметрах, в противном случае будет использоваться системный часовой пояс или информация о языке по умолчанию.
так какРазличные часовые пояса и национальные языки имеют различный вывод информации о времени и годе-месяце-дне., так что это одна из причин, по которой экземпляр календаря должен передавать информацию о часовом поясе и стране. См. пример:
public static void main(String[] args){
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getTime());
Calendar calendar1 = Calendar.getInstance
(TimeZone.getTimeZone("GMT"), Locale.ENGLISH);
System.out.println( calendar1.get(Calendar.YEAR) + ":" +
calendar1.get(Calendar.HOUR) + ":" +
calendar1.get(Calendar.MINUTE));
}
Выходной результат:
Sat Apr 21 10:32:20 CST 2018
2018:2:32
Видно, что первый вывод - это часовой пояс нашей системы по умолчанию и текущее время страны, а второму экземпляру Calendar мы указали, что он находится в часовом поясе Гринвича (0 часовой пояс), результат также очевиден, разница составляет восемь часов, т. е. поскольку мы находимся в восточном восьмом округе, время на восемь часов раньше, чем часовой пояс 0.
Некоторым может быть интересно, почему выходные данные второго экземпляра Calendar такие сложные и связанные, вместо того, чтобы вызывать метод getTime напрямую, как это делает первый экземпляр Calendar?
Это связано с внутренней реализацией календаря, давайте посмотрим:
protected long time;
public final Date getTime() {
return new Date(getTimeInMillis());
}
Как и Date, Calendar хранит информацию о моменте внутри себя, а метод getTime фактически создает объект Date на основе этого момента и возвращает его.
Как правило, когда мы создаем экземпляр календаря, мы не передаем информацию о времени, поэтому, когда значение этого времени инициализируется, программа рассчитает количество миллисекунд в соответствии с системным часовым поясом по умолчанию и текущим временем и назначит его для время.
Таким образом, во всех экземплярах календаря, которые не изменяли вручную значение атрибута времени, значением времени является значение момента в часовом поясе системы по умолчанию в это время. То есть выходной результат getTime не будет обращать внимание на информацию о часовом поясе, соответствующую текущему экземпляру, что, на мой взгляд, также является недостатком дизайна календаря, потому что это приведет к тому, что значение вывода getTime для экземпляров календаря будет в двух экземплярах. различные часовые пояса, чтобы зависеть только от экземпляра Время выполнения системы во время инициализации.
Calendar также определяет множество статических констант и некоторые массивы атрибутов:
public final static int ERA = 0;
public final static int YEAR = 1;
public final static int MONTH = 2;
public final static int WEEK_OF_YEAR = 3;
public final static int WEEK_OF_MONTH = 4;
public final static int DATE = 5;
....
protected int fields[];
protected boolean isSet[];
...
Вся важная информация о дате хранится в массиве атрибутов, и значение этих статических констант часто представляет собой значение индекса.Через метод get мы передаем индекс атрибута и возвращаем значение атрибута. Например:
Calendar myCalendar = Calendar.getInstance();
int year = myCalendar.get(Calendar.YEAR);
Метод get здесь фактически напрямую принимает fields[1] в качестве возвращаемого значения, а массив атрибутов fields был рассчитан и назначен системой в соответствии с часовым поясом и языком при инициализации экземпляра Calendar.Обратите внимание, что расчет будет выполняться в соответствии с указанным вами часовым поясом, в отличие от времени, которое всегда соответствует системному часовому поясу по умолчанию..
Лично мне дизайн Календаря кажется элегантным и неразумным, ведь он «античный» и со временем будет заменен.
Преобразование формата DateFormat
Как мы видим из нашего предыдущего примера, Календарю очень хлопотно выводить информацию о дате в ожидаемом формате, и ее нужно прошивать вручную. И наш DateFormat используется для обработки преобразования между форматированными строками и датой и временем.
Как и Calendar, DateFormat также является абстрактным классом. Нам нужно генерировать его объекты-экземпляры через фабрики. В основном существуют следующие фабричные методы:
//只处理时间的转换
public final static DateFormat getTimeInstance()
//只处理日期的转换
public final static DateFormat getDateInstance()
//既可以处理时间,也可以处理日期
public final static DateFormat getDateTimeInstance()
Конечно, у каждого из них есть свои перегруженные методы, которые мы увидим позже.
DateFormat имеет два типа методов: format и parse.
public final String format(Date date)
public Date parse(String source)
Метод format используется для форматирования объекта даты в строку, а метод parse используется для преобразования отформатированной строки в объект даты. Например:
public static void main(String[] args){
Calendar calendar = Calendar.getInstance();
DateFormat dateFormat = DateFormat.getDateTimeInstance();
System.out.println(dateFormat.format(calendar.getTime()));
}
Выходной результат:
2018-4-21 16:58:09
Очевидно, что использование созданного на заводе экземпляра DateFormat не может настроить содержимое выходного формата, то есть формат выходной строки является фиксированным и в некоторых случаях не может удовлетворить особые потребности. Как правило, мы будем напрямую использовать один из его классов реализации, SimpleDateFormat.
SimpleDateFormat позволяет передавать параметр шаблона при создании экземпляра для настройки выходного формата символов даты. Например:
public static void main(String[] args){
DateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日");
System.out.println(dateFormat.format(new Date()));
}
Выходной результат:
2018年04月21日
в,
- yyyy: год выводится четырьмя цифрами
- Мм: месяц с двумя выходами
- ДД: двойка представляет информацию о дне.
- HH: Две цифры для часов
- мм: две цифры для минут
- ss: две цифры для представления секунд
- E: Указывает день недели, если языковой стандарт находится в Китае, он выводит неделю x, если он находится в Соединенных Штатах или Соединенном Королевстве, он выводит неделю на английском языке.
- a: означает утро или день
Конечно, также очень удобно преобразовывать строки в даты, допуская пользовательские шаблоны, но вы должны следовать своим собственным шаблонам, иначе программа не сможет успешно выполнить синтаксический анализ. Например:
public static void main(String[] args){
String str = "2018年4月21日 17点17分 星期六";
DateFormat sDateFormat = new SimpleDateFormat("yyyy年M月dd日 HH点mm分 E");
sDateFormat.parse(str);
System.out.println(sDateFormat.getCalendar().getTime());
}
Выходной результат:
Sat Apr 21 17:17:00 CST 2018
Судя по всему, программа правильно анализирует нашу строку и преобразует ее в объект Calendar, хранящийся внутри DateFormat.
В общем, Date, Calendar и DateFormat смогли решить общие проблемы со временем и датой, но неизбежно они по-прежнему громоздки и сложны в использовании.
Из-за нехватки места мы сравним новый API даты и времени Java 8 в следующей статье, и вы найдете его более элегантный дизайн и простое управление.
Весь код, изображения, файлы в статье хранятся в облаке на моем GitHub:
(https://github.com/SingleYam/overview_java)
Добро пожаловать в публичный аккаунт WeChat: Gorky on the code, все статьи будут синхронизированы в публичном аккаунте.