Since the release of Java 8 in 2014, our ancient java.util.Date is finally no longer the only choice for operating dates and time in Java.
In fact, the related APIs of date and time in Java have always been criticized by the world. Not only is it not only because its design division is unclear, but it often can handle both dates and time, which is very confusing. It also numerical mappings of certain years, months and dates are stored against humans, such as: 0 corresponds to month January, 11 corresponds to month December, 118 corresponds to year 2018 (1900 + 118), etc.
Often, when we get a certain year and month value, we need to do corresponding operations to obtain accurate year, month and date information. Until our Java 8, we borrowed the excellent design of the third-party open source library Joda-Time, and redesigned a date and time API. Compared with the previous one, it can be said that it is a hundred times easier to use. All the related API interfaces are located in the package java.time.
Ancient date and time interface
Date representing the time information
All computers in the world use an integer of type long, and the value of this integer is the number of milliseconds relative to GMT in the UK (0:0:00, January 1, 1970). For example:
public static void main(String[] args){ //January 1, 1970 00:00:00 GMT. Date date = new Date(1000); System.out.println(date);}Output result:
//1970-1-1 8:00:01Thu Jan 01 08:00:01 CST 1970
Many people may wonder, 1000 means 1 second before standard time, so why does the time pass eight hours more?
This has something to do with the "time zone". If you are located in Greenwich, the result will be as expected, but we are located in the East Eighth District of China, and the time is eight hours earlier, so the basic values based on different time zones are different.
The Date class has really played many roles before. It can be seen from its source code that there are methods that can operate time, methods that can operate year, month and day, and even manage time zones. It can be said that it is enough to have it on the date and time related operations alone.
But this is the world. If you care about too much, you will naturally not be able to cover everything. The design of many methods in Date is not very reasonable. We have also said it before, and it is even a bit anti-human. Therefore, nearly 80% of the methods in the current Date class have been abandoned and are marked @Deprecated.
The current positioning of sun company for Date is to represent a moment only, so its internal position should revolve around the milliseconds of that integer, and no longer focus on various annual calendar time zones and other information.
Date allows an object to be instantiated through two constructors:
private transient long fastTime;public Date() { this(System.currentTimeMillis());}public Date(long date) { fastTime = date;}The fastTime attribute here stores the number of milliseconds corresponding to the time. The two constructors are still very simple. If the parameterless constructor is called, the virtual machine will assign fastTime with the current time value of the system.
There are a few other methods that have not been discarded:
There are two other methods that are newly added to jdk1.8 afterwards, and are used to convert new interfaces to Java 8, which will be introduced later.
Calendar describing the almanac
Calendar is used to represent date information such as year, month, day, etc. It is an abstract class, so its instance object is generally obtained through the following four factory methods.
public static Calendar getInstance()public static Calendar getInstance(TimeZone zone)public static Calendar getInstance(Locale aLocale)public static Calendar getInstance(TimeZone zone,Locale aLocale)
In fact, the same internal method will eventually be called:
private static Calendar createCalendar(TimeZone zone,Locale aLocale)
This method requires two parameters, one is the time zone and the other is the country and language. That is to say, building a Calendar instance requires at least these two parameter information, otherwise the system default time zone or language information will be used.
Because different time zones and national languages output differently for time and year, month and day information, this is also a reason why a Calendar instance must pass in time zone and country information. See an example:
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)); }Output result:
Sat Apr 21 10:32:20 CST 20182018:2:32
As you can see, the first output is the current time of our system's default time zone and the country, and the second Calendar instance we specified that it is located in the Greenwich Time Zone (0 time zone), and the result is also obvious, with an eight hour difference, because we are located in the East Eighth, which is eight hours earlier than the 0 time zone.
Some people may wonder why the output of the second Calendar instance is so complicated to splice, rather than calling the getTime method directly concise like the first Calendar instance?
This involves the internal implementation of Calendar, let's take a look together:
protected long time;public final Date getTime() { return new Date(getTimeInMillis());}Like Date, Calendar maintains a time information inside, and the getTime method actually builds a Date object based on this time and returns.
Generally, when we build a Calendar instance, we will not pass in a time information, so when the instance is initialized, the program will calculate a millisecond number based on the system's default time zone and current time and assign it to the time.
Therefore, inside all Calendar instances whose time attribute value has not been manually modified, the time value is the time value of the default time zone at that time. In other words, the output result of getTime ignores the time zone information corresponding to the current instance. This is also a flaw in the Calendar design, because this will cause the getTime output value of the two Calendar instances to depend only on the running time of the system when the instance is initialized.
Calendar also defines many static constants and some attribute arrays:
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[];...
All relevant information about dates is stored in the attribute array, and the values of these static constants often represent an index value. Through the get method, we pass in an attribute index and return the value of the attribute. For example:
Calendar myCalendar = Calendar.getInstance();int year = myCalendar.get(Calendar.YEAR);
The get method here is actually to directly take fields[1] as the return value. The fields attribute array is calculated and assigned by the system according to the time zone and language when the Calendar instance is initialized. Note that it will be calculated based on the time zone you specified, unlike time, which is always based on the system default time zone.
I personally think that Calendar's design has elegant and unreasonable aspects. After all, it is an "antique" and will eventually be replaced.
DateFormat format conversion
As we can see from one of our previous examples, it is very troublesome to output date information in an expected format for Calendar and needs to be spliced manually. Our DateFormat is used to handle the conversion between formatted strings and datetimes.
Like Calendar, DateFormat is also an abstract class. We need to generate its instance object through factory methods. There are mainly the following factory methods:
//Only process time conversion public final static DateFormat getTimeInstance()//Only process date conversion public final static DateFormat getDateInstance()//You can handle both time and date public final static DateFormat getDateTimeInstance()
Of course, they each have their own overloading methods, and we will see the details later.
There are two types of methods for DateFormat, format and parse.
public final String format(Date date)public Date parse(String source)
The format method is used to format a date object as a string, and the parse method is used to replace a formatted string with a date object. For example:
public static void main(String[] args){ Calendar calendar = Calendar.getInstance(); DateFormat dateFormat = DateFormat.getDateTimeInstance(); System.out.println(dateFormat.format(calendar.getTime()));}Output result:
2018-4-21 16:58:09
Obviously, a factory-constructed DateFormat instance cannot customize the output formatting content, that is, the output string format is fixed and cannot meet the special needs in some cases. Generally, we will directly use one of its implementation classes, SimpleDateFormat.
SimpleDateFormat allows you to pass a pattern parameter when constructing an instance to customize the output format of date characters. For example:
public static void main(String[] args){ DateFormat dateFormat = new SimpleDateFormat("yyyyy year MM month dd day"); System.out.println(dateFormat.format(new Date()));}Output result:
April 21, 2018
in,
Of course, it is also very convenient to convert string dates. Customized modes are allowed, but you must abide by the patterns you set by yourself, otherwise the program will not be able to successfully parse. For example:
public static void main(String[] args){ String str = "Saturday, April 21, 2018"; DateFormat sDateFormat = new SimpleDateFormat("yyyy year M month dd day HH point mm point E"); sDateFormat.parse(str); System.out.println(sDateFormat.getCalendar().getTime());}Output result:
Sat Apr 21 17:17:00 CST 2018
Obviously, the program is correctly parsing our string and converting it to a Calendar object stored inside DateFormat.
In general, Date, Calendar and DateFormat have been able to handle general time and date issues, but inevitably, they are still cumbersome and difficult to use.
Due to space limitations, we will compare Java 8's new date and time API in the next article, and you will find that it has a more elegant design and simple operation.