If your Java application presents dates and times to users in different time zones or countries, you will need to understand some of the more advanced aspects of the Java date classes. In “Calculate, customize, and parse dates with Java Date and Calendar classes,” we offered a basic overview of dates, date formatting, date parsing, and date calculations. A good understanding of those concepts is crucial before taking on more advanced date issues, such as time zones, internationalized formatting, and SQL dates.
The classes we’ll cover in this article include more on java.text.DateFormat, as well as java.util.TimeZone and java.util.Locale. We’ll also look at using a subclass of java.util.Date, java.sql.Date, to retrieve and store Java dates in an Oracle database.
Locales
Before we can internationalize our dates, we need to know a little bit about the Locale class, java.util.Locale. An instance of the Locale class typically includes the country and language. Each is a two-character string based on the International Organization for Standardization (ISO) Country Code ISO-3166 and Language Code ISO-639, respectively. For more information on Locales, visit Sun’s Web site.
Let’s create two Locales, one for the English language in the United States and one for the French language in France. See Listing A.
In the example, we use the getDisplayName method to print out a more readable description of the Locale. Also note that in the last call to getDisplayName, we passed in the French Locale when calling getDisplayName on the English Locale. This allows us to display the Locale used in the language of choice, giving us the English DisplayName in French. Here is the output from the example:
Display Name: English (United States)
Country: US
Language: en
Display Name: French (France)
Country: FR
Language: fr
en Display Name in French: anglais (États-Unis)
Date formatting for multiple locales
Using java.util.Locale and java.text.DateFormat, let’s format dates for display to users in another locale, such as France. The example in Listing B creates a full date formatter for English and one for French.
The output of the example is:
Locale: French (France)
vendredi 5 octobre 2001 21 h 05 GMT-04:00
Locale: English (United States)
Friday, October 5, 2001 9:05:54 PM EDT
Notice that the output includes time zone information: GMT-04:00 and PM EDT. The time zone was captured from the system’s time zone setting. As you can see, the dates are displayed in a format that a user in that locale would expect. Let’s look at time zones next.
Time zones
An instance of the TimeZone class, java.util.TimeZone, includes a time zone offset in milliseconds from Greenwich Mean Time (GMT) and handles Daylight Saving Time. For a list of all supported time zones, use the method TimeZone.getAvailableIDs, which will return a string array of all IDs. For more details on the TimeZone class, refer to Sun’s Web site.
To demonstrate, we’ll create three time zone objects. The first object will use getDefault, which returns the time zone from the system clock; the second and third objects will pass in a time zone string ID. See the code in Listing C.
The output will look like this:
Eastern Standard Time
RawOffset: -18000000
Uses daylight saving: true
GMT+00:00
RawOffset: 0
Uses daylight saving: true
Central European Standard Time
RawOffset: 3600000
Uses daylight saving: true
As you can see, the TimeZone objects give us the raw offset, which is the number of milliseconds from GMT, and tells us whether the time zone uses daylight saving. With this information, we’ll be able to proceed to combining time zone objects with date formatters to display time in other time zones and in other languages.
Internationalized display and time zone conversion
Let’s look at an example that combines internationalization, time zones, and date formatting. Listing D shows the current full date and time for a company that has offices in Miami and in Paris. For the Miami office, we’ll show the full date and time in English at each office. For the Paris office, we’ll show the full current date and time in French at each office.
The output of the example is:
Display for Miami office.
Eastern Standard Time
Friday, October 5, 2001 10:28:02 PM EDT
Central European Standard Time
Saturday, October 6, 2001 4:28:02 AM CEST
Display for Paris office.
GMT-05:00
vendredi 5 octobre 2001 22 h 28 GMT-04:00
GMT+01:00
samedi 6 octobre 2001 04 h 28 GMT+02:00
Saving and retrieving dates from a SQL database
The next class to look at is java.sql.Date, which is a subclass of java.util.Date but is designed to be used with Java Database Connectivity (JDBC) methods. Let’s look at a simple Oracle database that has one table, LAST_ACCESS, created using the following SQL:
create table LAST_ACCESS (
LAST_HIT date
);
The table has just one record, created using the following insert statement:
insert into LAST_ACCESS values (Sysdate);
Listing Eshows how to update and retrieve the LAST_HIT database field.
The output of the example is:
Friday, October 5, 2001 10:42:34 PM EDT
Rows updated: 1
Successfully retrieved last hit.
Friday, October 5, 2001 12:00:00 AM EDT
While this example does not provide the optimal method for setting and getting dates in terms of performance, it does illustrate how to convert the Java date to the SQL date for an update statement and an insert statement. The complexities of setting the Oracle date field from a java.util.Date object are handled by this line of code:
ps.setDate(1, date);
which is a method in the prepared statement interface java.sql.PreparedStatement.setDate.
This line is in our setLastHit method. It handles converting our Java millisecond long date value to Oracle’s SQL date format. The reverse is true when retrieving the date from the database using java.sql.PreparedStatement.getDate in our getLastHit method.
It is also important to note that only the date was set. The hours, minutes, seconds, and milliseconds were not included in the conversion from a Java date to a SQL date.
Conclusion
Once you master these concepts, you should be able to create date objects based on the system time or an entered time. Additionally, you should be able to format dates using standard formatting and customized formatting, parse textual dates into date objects, and display a date in multiple time zones in multiple languages. You should also be able to store and retrieve date values in a SQL database. Not too shabby.
Do your apps span time zones and countries?
What problems have you encountered with internationalization of your applications? What tips do you have for others developing this type of program? Send us an e-mail with your experiences and suggestions or post a comment below.