Introduction
On the computerProgramIt is difficult to accurately process the date in. Not only are there obvious (English: January, French: Janvier, German: Januar, etc.) Internationalization requirements, different date systems must also be considered (not all cultures use the birthday of Jesus Christ as the beginning of the year ). If there is a high precision or a very large amount of time to be processed, there are additional aspects that need attention, such as leap second or time system changes. (Gregorian calendar) is widely accepted in the west in 1582, but not all countries accept it on the same day !)
Although there is a problem with the time of a leap second, time zone, Daylight Saving Time, And the lunar calendar, the measurement time is a very simple concept: the time is linear and easy to ignore. Once the region of the timeline is defined, any time point can be determined by the passage of time from the start point. This is independent from the geographical location or local time zone-the process of starting from any specified time point to any region is the same (ignoring the correction of relativity ).
--------------------------------------------------------------------------------
But when we try to explain this time point based on some calendars, for example, it is represented by month, day, or year. In this step, the geographical information becomes related: the same point in time corresponds to a time in a different day, depending on the region (such as the time zone ). Correction Based on the interpretation date is often necessary (which day is the next month ?) In addition, it adds extra difficulties: overflow and underflow (the next month in December 15 is the next year), and it is not clear (which day is the month after January 30 ?).
In the original JDK 1.0, a time point is interpreted as Java. util. date class, which is computed together for representation. although relatively easy to handle, it does not support internationalization; from JDK 1.1.4 or JDK 1.1.5, various responsibilities for handling dates are assigned to the following categories:
Java. util. Date
Represents a time point.
Abstract java. util. Calendar
Java. util. gregoriancalendar extends java. util. Calendar
Interpret and process date.
Abstract java. util. timezone
Java. util. simpletimezone extends java. util. timezone
Represents an arbitrary offset from Greenwich Mean. It also contains information applicable to daylight savings rules.
Abstract java. Text. dateformat extends java. Text. Format
Java. Text. simpledateformat extends java. Text. dateformat
Deformation to a well-formatted, printable string, and vice versa.
Java. Text. dateformatsymbols
The translation of months and weeks is an alternative to obtaining information from locale.
Java. SQL. Date extends java. util. Date
Java. SQL. time extends java. util. Date
Java. SQL. timestamp extends java. util. Date
It indicates the time point and also contains the appropriate format for use in SQL statements.
Note: dateformat and related classes are available in Java. text. * package. all Java. SQL. * The date processing class in the package inherits Java. util. date class. all other classes in Java. util. * package.
These "new" classes come from three isolated inheritance layers, and their top-level classes (calendar, timezone, and dateformat) are abstract. for each abstract class, the java standard library provides a specific implementation.
Java. util. Date
Class Java. util. date indicates a time point. in many applications, this abstraction is called "timestamp. "In the standard Java class library implementation, this time point represents the number of milliseconds since January 1, 1970, and 00:00:00 GMT. in terms of concept, this class is a simple encapsulation of long.
According to this explanation, only the get and set methods in the class that have not expired (except those in milliseconds) are those sorting methods.
This class relies on system. currenttimemillis () to obtain the current time point. Therefore, its accuracy and accuracy are determined by the implementation of the system and the underlying layer (essentially the operating system) It calls.
The Java. util. Date API
In the use of the original date class, the names and conventions lead to endless confusion. however, in the 0-11 computing month, the decision from the 1900 computing year imitates the habit of C standard library, and calls the gettime () function to return the number of milliseconds starting from the Unix era and getdate () the decision to return the week is obviously made by the Java class designer.
Java. util. Calendar
Semantics
Calendar represents a time point (a "date"), which is used as an interpreter in a specific region and time zone. each calendar instance has a long variable that represents a time point starting from the epoch.
This means that calendar is not a (stateless) converter or interpreter, nor a factory for modifying dates. It does not support the following methods:
Month interpreter. getmonth (inputdate) or
Date factory. addmonth (inputdate)
Instead and calendar instances must be initialized to a specific date. This calendar instance can be modified or queried for interpreted attributes.
It is strange that such instances is always initialized to the current time. it is impossible to obtain a calendar instance initialized to any date-the API forces programmers to explicitly set the date by calling a series of methods on the instance, such as settime (date.
Access interpreted fields and class Constants
The calendar class accesses a single field of the interpreted date instance in an uncommon way. instead of providing some dedicated attributes getters and setters methods (such as getmonth (), it only provides one method that uses a tag as a parameter to obtain the request attributes:
Int get (calendar. month) and so on.
Note that this function always returns an int!
The identifiers of these fields are defined as the public static final variable of the calendar class. (These identifiers are raw integers and are not encapsulated as enumeration abstractions .)
In addition to the field identifier (key value), the calendar class defines many additional public static final variables to save the values of these fields. therefore, to test whether a specified date (represented by the calendar instance calendar) is in the first month of the yearCode:
If (calendar. Get (calendar. month) = calendar. January ){...}
Note that the month is called January and February, regardless of location (more neutral names such as month_1 and month_2 ). there is also a field undecimber, which is used by some calendars (non-Gregorian calendar (Gregorian calendar, gregalli calendar), representing the 13th months of a year.
Unfortunately, the key value and value are neither identified by a name nor a nested inerface.
Processing
Calendar provides three methods to modify the date represented by the current instance: Set (), add (), and roll (). the Set () method simply sets a specific field as the expected value. the difference between add () and roll () is that they process over-and underflows: add () and pass changes to "smaller" or "larger" fields, while Roll () other fields are not affected. for example, if you add a month to a calendar instance that represents December 15, when add () uses the Annual Meeting, but roll () does not change. the motive behind the corresponding function for each case is that they may be used differently in the GUI.
Because of the implementation of the calendar, it contains redundant data: all fields can be calculated from the given time zone and the number of milliseconds since the epoch, and vice versa. this class defines the Abstract METHODS computefields () and computetime () for these operations, and defines the complete round-trip execution of the complete () method. because there are two sets of redundant data, these two sets of data may not be synchronized. according to the javadoc document of the class, the dependent data is recalculated in lazily mode when the change occurs. when re-calculation is required, the subclass must maintain a set of dirty data signs as symbols.
--------------------------------------------------------------------------------
Implemented Leakage
For a "new" date-related processing class, we have to say that the implementation details are leaked to the API to some extent. at this point, this is a reflection of their intention to be used as a custom development for the base class, but it also happens that it is not fully clear about the results of designing a public interface. whether the calendar abstraction maintains two redundant data sets is completely an implementation detail and should be hidden from the customer class. this also includes the intention to reuse this class through inheritance.
Additional features
The calendar base class provides three additional functions. several static factory methods are used to obtain instances initialized using any time zone and locales. as mentioned above, all instances obtained in this way have been initialized to the current time. no factory method is provided to obtain instances initialized to any time point.
The second group contains the before (object) and after (object) methods. They accept parameters of the object type and therefore allow these methods to be overwritten by parameters of any type.
Finally, there are many additional methods to obtain additional attributes, such as the current time zone. There are several methods used to query the possible and actual maximum and minimum values of a specific field in the current calendar implementation.
Java. util. gregoriancalendar
Gregoriancalendar is a subclass of only available calendar. it provides basic calendar abstraction suitable for interpreting date implementations based on Western habits. it adds many public constructors, as well as methods for Gregorian calendars, such as isleapyear ().
Java. util. timezone and Java. util. simpletimezone
The timezone class and its subclass are helper classes, which are used by calendar to explain the date based on the selected time zone. literally, a time zone represents a certain offset to the current time zone after it is added to GMT. obviously, this offset will change when it is valid during begin. therefore, to calculate the local time of a given date and time, the timezone abstraction not only needs to understand the additional offset when DST is valid, but also the rule when DST is valid.
Abstract base-class timezone provides basic processing "Raw" (when the SWAp is not considered) Actual offset (in milliseconds !) But any implementation of DST rules is left to subclasses, such as simpletimezone. the latter provides a number of methods to specify rules for controlling the start and end of DST, such as specifying the day of a month or the day of the following week. each timezone has a readable, locally independent display name. the display name is displayed in two styles: long and short.
Start of the week?
Calendar documents have invested a considerable amount of text to calculate weeks in a month or year. weekday is regarded as the beginning of a week in different countries. in the United States, a week is generally considered to start from Sunday. in some European countries, the week ends from Monday to Sunday. this will affect which week is considered to be the first complete week of the year (or month), and calculate the number of weeks of the year.
The time zone is determined by a specific string. the base class provides the static method string [] getavailableids () to obtain standard time zones for all known installations (included in JDK. (There are 557 jdk1.4.1 in my installation) If necessary, javadoc defines a strict syntax for creating custom Time Zone identifiers. the static factory method is also provided to get the timezone instance with the specified ID or default current time zone. simpletimezone provides some public constructor. It is strange that for an abstract class, such as timezone. (javadoc writes "subclass constructor call. "Obviously, it should be declared as protected .)
Java. Text. dateformat
Although the calendar and related classes process the interpretation of locale-specific dates, there are still dateformat class secondary date and (human) readable conversions between strings. indicating a time point, there will be additional localization issues: not only in the language, but also the date format is region independent (United States: Month/day/year, Germany: Day. month. year, and so on ). dateformat tries its best to manage these differences for programmers.
The abstract base class dateformat does not need (and is not allowed) any date format defined by the programmer. as an alternative, it defines four formatting styles: short, medium, long, and full (in the order of increased redundancy ). for a given locale and style, programmers can rely on this class to obtain the appropriate date format.
The abstract base class dateformat does not define static methods for formatting and conversion between text and date. as an alternative, it defines several static factory methods to obtain instances initialized to a given locale and selected style. since standard formatting always includes date and time, the additional factory method can be used to obtain instances that only process time or date. the string format (date) and date parse (string) methods are then deformed. note that the specific subclass can be used to break this habit.
In its internal use, the Calendar Object that explains the date can be accessed and modified, and the timezone and numberformat objects are the same. However, once dateformat is instantiated, locale and style cannot be modified.
There are also available (abstract) string parsing and formatting methods for splicing, respectively accepting additional parseposition or fieldposition parameters. each of these methods has two versions. one accepts or returns the date instance, and the other accepts or returns normal objects to allow the subclass to selectively process the date. it defines some public static variables ending with _ field to mark a variety of variables that may be used with fieldposition (cf. java. util. format javadoc ).
The only and most common implementation of the dateformat class is simpledateformat. it provides all of the above functions and allows the definition of any time format. a rich set of syntax to specify the formatting mode; javadoc provides all the details. mode can be specified as a constructor parameter or explicitly set.
Printing a timestamp: a cut-and-paste example
Imagine you want to print the current time in a user-defined format. For example, to log files, the following is what you do:
// Create a mode in the following format: hour (0-23): minute: Second
Simpledateformat formatter = new simpledateformat ("HH: mm: SS ");
Date Now = new date ();
String logentry = formatter. Format (now );
// Read data from the backend
Try {
Date sometime = formatter. parse (logentry );
} Catch (parseexception exc ){
Exc. printstacktrace ();
}
Note that the parseexception to be caught is thrown when the input string cannot be parse.
Java. SQL. * Related Classes
In Java. SQL. * The date and time processing class in the package inherits Java. util. date. in fact, the three of them reflect the types required for the three standard sql92 models: date, time, and timestamp.
Such as Java. util. these three classes in the SQL package are simple encapsulation of numbers that represent a time point. the date and time classes ignore the date of the time or calendar in a day.
The timestamp class not only contains millisecond precision, common time and date, but also allows the storage of additional data precise to the time point of the nanoseconds (the nanoseconds are one thousandth of a second)
In addition to the corresponding SQL data types, these classes process the conversion of string representation consistent with SQL. at this point, each of the three classes overwrites the tostring () method. in addition, each class provides a static factory method, valueof (string), which returns the instance of the current call class that is initialized as the time when the parameter string is passed. the format of the strings in these three methods has been selected by the SQL standard and cannot be changed by programmers.
The extra data required to store the nanoseconds is not exactly the same as the representation of other common time and date information in timestamp. for example, calling gettime () on a timestamp instance will return the number of milliseconds since the Unix epoch, ignoring the nanoseconds of data. in short, according to The javadoc documentation, the hashcode () method is not overwritten in the subclass, and therefore the nanosecond data is ignored.
Java. SQL. timestamp javadoc indicates "inheritance relationship (...) actually represents the inheritance of implementation, rather than the type inheritance (this violates the original intention of inheritance ). however, even if this sentence is incorrect, since Java does not have the concept of private inheritance (that is, inheritance implementation ). all Java. SQL. * classes in the package should be designed to encapsulate a java. util. date object, instead of inheriting it, only expose the required methods-at least, methods such as hashcode () should be appropriately overwritten.
The last comment is about how to process the time zone of the database engine. in Java. SQL. * classes in the package cannot explicitly set the time zone. the Database Server (or driver) can freely interpret the information based on the local time zone of the server, and the information may be affected and changed (for example, because of the failover time ).
Summary
As discussed above, it is clear that the date Processing classes in Java are not very complex, but they are not well designed. encapsulation is neglected. The structure of APIS is complex and not well organized, and the uncommon ideas are often ignored. the implementation is even more inexplicable (I suggest you look at the calendar. getinstance (locale) indicates the type of the actually returned object for all available locale !) On the other hand, the classes manage to treat all of the difficulties inherent in internationalized date handling and, in any case, are here to stay.ArticleIt helps you understand their usage.
Call me by my true names
As a last example of the wonderful consistency and orthogonality of Java's APIs, I wowould like to list three (maybe there are more !) Different methods to obtain the number of milliseconds since the start of the UNIX epoch:
Long java. util. Date. gettime ()
Long java. util. Calendar. gettimeinmillis () (new with JDK 1.4.1. Note that Java. util. Calendar. gettime () returns a date object !)
Long java. Lang. system. currenttimemillis ()
Thanks
I am very grateful to Wilhelm Fitzpatrick for his careful reading of the draft and valuable comments.
References
International calendars in Java at IBM: A detailed White Paper by one of the original authors on the genesis and intended usage of Java's date-handling classes. Highly recommended.
IBM alphaWorks: International calendars: Additional subclasses of calendar for Buddhist, Hebrew, Muslim, and Japanese calendars used to be available at IBM's alphaWorks. schedule, they seem to be temporarily unavailable.
Reingold on calendars: web site of Edward M. Reingold, author of calendrical calculations, the standard reference on calendars.
About the calendars: a brief overview of some of the more common international calendars.
Thread on javalobby: a brief, but interesting, thread on javalobby. apparently, some people considered the APIs of Java's date classes to be so bad that they filed an official bug-report to have them changed. unfortunately, the request has been rejected.
Philipp K. janert, Ph. D. is a software project consultant, server programmer, and effecect.