Date and Time


When you are formatting date and time, you should be concerned with four locale-dependent issues:

  • The names of months and weekdays should be presented in the local language.

  • There will be local preferences for the order of year, month, and day.

  • The Gregorian calendar may not be the local preference for expressing dates.

  • The time zone of the location must be taken into account.

The Java DateFormat class handles these issues. It is easy to use and quite similar to the NumberFormat class. First, you get a locale. You can use the default locale or call the static getAvailableLocales method to obtain an array of locales that support date formatting. Then, you call one of the three factory methods:

 fmt = DateFormat.getDateInstance(dateStyle, loc); fmt = DateFormat.getTimeInstance(timeStyle, loc); fmt = DateFormat.getDateTimeInstance(dateStyle, timeStyle, loc); 

To specify the desired style, these factory methods have a parameter that is one of the following constants:

DateFormat.DEFAULT

DateFormat.FULL (e.g., Wednesday, September 15, 2004 8:51:03 PM PDT for the U.S. locale)

DateFormat.LONG (e.g., September 15, 2004 8:51:03 PM PDT for the U.S. locale)

DateFormat.MEDIUM (e.g., Sep 15, 2004 8:51:03 PM for the U.S. locale)

DateFormat.SHORT (e.g., 9/15/04 8:51 PM for the U.S. locale)

The factory method returns a formatting object that you can then use to format dates.

 Date now = new Date(); String s = fmt.format(now); 

Just as with the NumberFormat class, you can use the parse method to parse a date that the user typed. For example, the following code parses the value that the user typed into a text field, using the default locale.

 TextField inputField; . . . DateFormat fmt = DateFormat.getDateInstance(DateFormat.MEDIUM); Date input = fmt.parse(inputField.getText().trim()); 

If the number was not typed correctly, this code throws a ParseException. Note that leading whitespace in the string is not allowed here, either. You should again call trim to remove it. However, any characters that follow the number in the string will again be ignored. Unfortunately, the user must type the date exactly in the expected format. For example, if the format is set to MEDIUM in the U.S. locale, then dates are expected to look like

 Sep 18, 1997 

If the user types

 Sep 18 1997 

(without the comma) or the short format

 9/18/97 

then a parse error results.

A lenient flag interprets dates leniently. For example, February 30, 1999 will be automatically converted to March 2, 1999. This seems dangerous, but, unfortunately, it is the default. You should probably turn off this feature. The calendar object that interprets the parsed date will throw IllegalArgumentException when the user enters an invalid day/month/year combination.

Example 10-2 shows the DateFormat class in action. You can select a locale and see how the date and time are formatted in different places around the world. If you see question-mark characters in the output, then you don't have the fonts installed for displaying characters in the local language. For example, if you pick a Chinese locale, the date may be expressed as

 1997918 

Figure 10-2 shows the program (after Chinese fonts were installed). As you can see, it correctly displays the output.

Figure 10-2. The DateFormatTest program


You can also experiment with parsing. Enter a date or time, click the Parse lenient checkbox if desired, and click the Parse date or Parse time button.

We use a helper class EnumCombo to solve a technical problem (see Example 10-3). We wanted to fill a combo with values such as Short, Medium, and Long and then automatically convert the user's selection to integer values DateFormat.SHORT, DateFormat.MEDIUM, and DateFormat.LONG. Rather than writing repetitive code, we use reflection: We convert the user's choice to upper case, replace all spaces with underscores, and then find the value of the static field with that name. (See Volume 1, Chapter 5 for more details about reflection.)

TIP

To compute times in different time zones, use the TimeZone class. See http://java.sun.com/developer/JDCTechTips/2003/tt1104.html#2 for a brief tutorial.


Example 10-2. DateFormatTest.java
   1. import java.awt.*;   2. import java.awt.event.*;   3. import java.text.*;   4. import java.util.*;   5. import javax.swing.*;   6.   7. /**   8.    This program demonstrates formatting dates under various locales.   9. */  10. public class DateFormatTest  11. {  12.    public static void main(String[] args)  13.    {  14.       JFrame frame = new DateFormatFrame();  15.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  16.       frame.setVisible(true);  17.    }  18. }  19.  20. /**  21.    This frame contains combo boxes to pick a locale, date and  22.    time formats, text fields to display formatted date and time,  23.    buttons to parse the text field contents, and a "lenient"  24.    checkbox.  25. */  26. class DateFormatFrame extends JFrame  27. {  28.    public DateFormatFrame()  29.    {  30.       setTitle("DateFormatTest");  31.  32.       setLayout(new GridBagLayout());  33.       add(new JLabel("Locale"), new GBC(0, 0).setAnchor(GBC.EAST));  34.       add(new JLabel("Date style"), new GBC(0, 1).setAnchor(GBC.EAST));  35.       add(new JLabel("Time style"), new GBC(2, 1).setAnchor(GBC.EAST));  36.       add(new JLabel("Date"), new GBC(0, 2).setAnchor(GBC.EAST));  37.       add(new JLabel("Time"), new GBC(0, 3).setAnchor(GBC.EAST));  38.       add(localeCombo, new GBC(1, 0, 2, 1).setAnchor(GBC.WEST));  39.       add(dateStyleCombo, new GBC(1, 1).setAnchor(GBC.WEST));  40.       add(timeStyleCombo, new GBC(3, 1).setAnchor(GBC.WEST));  41.       add(dateParseButton, new GBC(3, 2).setAnchor(GBC.WEST));  42.       add(timeParseButton, new GBC(3, 3).setAnchor(GBC.WEST));  43.       add(lenientCheckbox, new GBC(0, 4, 2, 1).setAnchor(GBC.WEST));  44.       add(dateText, new GBC(1, 2, 2, 1).setFill(GBC.HORIZONTAL));  45.       add(timeText, new GBC(1, 3, 2, 1).setFill(GBC.HORIZONTAL));  46.  47.       locales = DateFormat.getAvailableLocales();  48.       for (Locale loc : locales) localeCombo.addItem(loc.getDisplayName());  49.       localeCombo.setSelectedItem(Locale.getDefault().getDisplayName());  50.       currentDate = new Date();  51.       currentTime = new Date();  52.       updateDisplay();  53.  54.       ActionListener listener = new  55.          ActionListener()  56.          {  57.             public void actionPerformed(ActionEvent event)  58.             {  59.                updateDisplay();  60.             }  61.          };  62.  63.       localeCombo.addActionListener(listener);  64.       dateStyleCombo.addActionListener(listener);  65.       timeStyleCombo.addActionListener(listener);  66.  67.       dateParseButton.addActionListener(new  68.          ActionListener()  69.          {  70.             public void actionPerformed(ActionEvent event)  71.             {  72.                String d = dateText.getText().trim();  73.                try  74.                {  75.                   currentDateFormat.setLenient(lenientCheckbox.isSelected());  76.                   Date date = currentDateFormat.parse(d);  77.                   currentDate = date;  78.                   updateDisplay();  79.                }  80.                catch (ParseException e)  81.                {  82.                   dateText.setText("Parse error: " + d);  83.                }  84.                catch (IllegalArgumentException e)  85.                {  86.                   dateText.setText("Argument error: " + d);  87.                }  88.             }  89.          });  90.  91.       timeParseButton.addActionListener(new  92.          ActionListener()  93.          {  94.             public void actionPerformed(ActionEvent event)  95.             {  96.                String t = timeText.getText().trim();  97.                try  98.                {  99.                   currentDateFormat.setLenient(lenientCheckbox.isSelected()); 100.                   Date date = currentTimeFormat.parse(t); 101.                   currentTime = date; 102.                   updateDisplay(); 103.                } 104.                catch (ParseException e) 105.                { 106.                   timeText.setText("Parse error: " + t); 107.                } 108.                catch (IllegalArgumentException e) 109.                { 110.                   timeText.setText("Argument error: " + t); 111.                } 112.             } 113.          }); 114.       pack(); 115.    } 116. 117.    /** 118.       Updates the display and formats the date according 119.       to the user settings. 120.    */ 121.    public void updateDisplay() 122.    { 123.       Locale currentLocale = locales[localeCombo.getSelectedIndex()]; 124.       int dateStyle = dateStyleCombo.getValue(); 125.       currentDateFormat = DateFormat.getDateInstance(dateStyle, currentLocale); 126.       String d = currentDateFormat.format(currentDate); 127.       dateText.setText(d); 128.       int timeStyle = timeStyleCombo.getValue(); 129.       currentTimeFormat = DateFormat.getTimeInstance(timeStyle, currentLocale); 130.       String t = currentTimeFormat.format(currentTime); 131.       timeText.setText(t); 132.    } 133. 134.    private Locale[] locales; 135.    private Date currentDate; 136.    private Date currentTime; 137.    private DateFormat currentDateFormat; 138.    private DateFormat currentTimeFormat; 139.    private JComboBox localeCombo = new JComboBox(); 140.    private EnumCombo dateStyleCombo = new EnumCombo(DateFormat.class, 141.       new String[] { "Default", "Full", "Long", "Medium", "Short" }); 142.    private EnumCombo timeStyleCombo = new EnumCombo(DateFormat.class, 143.       new String[] { "Default", "Full", "Long", "Medium", "Short" }); 144.    private JButton dateParseButton = new JButton("Parse date"); 145.    private JButton timeParseButton = new JButton("Parse time"); 146.    private JTextField dateText = new JTextField(30); 147.    private JTextField timeText = new JTextField(30); 148.    private JTextField parseText = new JTextField(30); 149.    private JCheckBox lenientCheckbox = new JCheckBox("Parse lenient", true); 150. } 

Example 10-3. EnumCombo.java
  1. import java.util.*;  2. import javax.swing.*;  3.  4. /**  5.    A combo box that lets users choose from among static field  6.    values whose names are given in the constructor.  7. */  8. public class EnumCombo extends JComboBox  9. { 10.    /** 11.       Constructs an EnumCombo. 12.       @param cl a class 13.       @param labels an array of static field names of cl 14.    */ 15.    public EnumCombo(Class cl, String[] labels) 16.    { 17.       for (int i = 0; i < labels.length; i++) 18.       { 19.          String label = labels[i]; 20.          String name = label.toUpperCase().replace(' ', '_'); 21.          int value = 0; 22.          try 23.          { 24.             java.lang.reflect.Field f = cl.getField(name); 25.             value = f.getInt(cl); 26.          } 27.          catch (Exception e) 28.          { 29.             label = "(" + label + ")"; 30.          } 31.          table.put(label, value); 32.          addItem(label); 33.       } 34.       setSelectedItem(labels[0]); 35.    } 36. 37.    /** 38.       Returns the value of the field that the user selected. 39.       @return the static field value 40.    */ 41.    public int getValue() 42.    { 43.       return table.get(getSelectedItem()); 44.    } 45. 46.    private Map<String, Integer> table = new TreeMap<String, Integer>(); 47. } 


 java.text.DateFormat 1.1 

  • static Locale[] getAvailableLocales()

    returns an array of Locale objects for which DateFormat formatters are available.

  • static DateFormat getDateInstance(int dateStyle)

  • static DateFormat getDateInstance(int dateStyle, Locale l)

  • static DateFormat getTimeInstance(int timeStyle)

  • static DateFormat getTimeInstance(int timeStyle, Locale l)

  • static DateFormat getDateTimeInstance(int dateStyle, int timeStyle)

  • static DateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale l)

    return a formatter for date, time, or date and time for the default locale or the given locale.

    Parameters:

    dateStyle, timeStyle

    One of DEFAULT, FULL, LONG, MEDIUM, SHORT


  • String format(Date d)

    returns the string resulting from formatting the given date/time.

  • Date parse(String s)

    parses the given string and returns the date/time described in it. The beginning of the string must contain a date or time; no leading whitespace is allowed. The date

    can be followed by other characters, which are ignored. Throws a ParseException if parsing was not successful.

  • void setLenient(boolean b)

  • boolean isLenient()

    set or get a flag to indicate whether parsing should be lenient or strict. In lenient mode, dates such as February 30, 1999 will be automatically converted to March 2, 1999. The default is lenient mode.

  • void setCalendar(Calendar cal)

  • Calendar getCalendar()

    set or get the calendar object used for extracting year, month, day, hour, minute, and second from the Date object. Use this method if you do not want to use the default calendar for the locale (usually the Gregorian calendar).

  • void setTimeZone(TimeZone tz)

  • TimeZone getTimeZone()

    set or get the time zone object used for formatting the time. Use this method if you do not want to use the default time zone for the locale. The default time zone is the time zone of the default locale, as obtained from the operating system. For the other locales, it is the preferred time zone in the geographical location.

  • void setNumberFormat(NumberFormat f)

  • NumberFormat getNumberFormat()

    set or get the number format used for formatting the numbers used for representing year, month, day, hour, minute, and second.


 java.util.TimeZone 1.1 

  • static String[] getAvailableIDs()

    gets all supported time zone IDs.

  • static TimeZone getDefault()

    gets the default TimeZone for this computer.

  • static TimeZone getTimeZone(String timeZoneId)

    gets the TimeZone for the given ID.

  • String getID()

    gets the ID of this time zone.

  • String getDisplayName()

  • String getDisplayName(Locale locale)

  • String getDisplayName(boolean daylight, int style)

  • String getDisplayName(boolean daylight, int style, Locale locale)

    get the display name of this time zone in the default locale or in the given locale. If the daylight parameter is true, the daylight-savings name is returned. The style parameter can be SHORT or LONG.

  • boolean useDaylightTime()

    returns true if this TimeZone uses daylight-savings time.

  • boolean inDaylightTime(Date date)

    returns true if the given date is in daylight-savings time in this TimeZone.



    Core JavaT 2 Volume II - Advanced Features
    Building an On Demand Computing Environment with IBM: How to Optimize Your Current Infrastructure for Today and Tomorrow (MaxFacts Guidebook series)
    ISBN: 193164411X
    EAN: 2147483647
    Year: 2003
    Pages: 156
    Authors: Jim Hoskins

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net