29.13. Programming Exercises

 
[Page 864 ( continued )]

26.3. Displaying Date and Time

Applications often need to obtain date and time. Java provides a system-independent encapsulation of date and time in the java.util.Date class; it also provides java.util.TimeZone for dealing with time zones, and java.util.Calendar for extracting detailed information from Date . Different locales have different conventions for displaying date and time. Should the year, month, or day be displayed first? Should slashes , periods, or colons be used to separate fields of the date? What are the names of the months in the language? The java.text.DateFormat class can be used to format date and time in a locale-sensitive way for display to the user . The Date class was introduced in §7.5.1, "The Date Class," and the Calendar class and its subclass GregorianCalendar were introduced in §10.3, "The Calendar and GregorianCalendar Classes."

26.3.1. The TimeZone Class

TimeZone represents a time zone offset and also figures out daylight savings. To get a TimeZone object for a specified time zone ID, use TimeZone.getTimeZone(id) . To set a time zone in a Calendar object, use the setTimeZone method with a time zone ID. For example, cal.setTimeZone(TimeZone.getTimeZone("CST")) sets the time zone to Central Standard Time. To find all the available time zones supported in Java, use the static method getAvailableIDs() in the TimeZone class. In general, the international time zone ID is a string in the form of continent /city like Europe/Berlin, Asia/Taipei, and America/Washington. You can also use the static method getDefault() in the TimeZone class to obtain the default time zone on the host machine.


[Page 865]

26.3.2. The DateFormat Class

The DateFormat class can be used to format date and time in a number of styles. The DateFormat class supports several standard formatting styles. To format date and time, simply create an instance of DateFormat using one of the three static methods getDateInstance , getTimeInstance , and getDateTimeInstance and apply the format(Date) method on the instance, as shown in Figure 26.2.

Figure 26.2. The DateFormat class formats date and time.

The dateStyle and timeStyle are one of the following constants: DateFormat.SHORT , DateFormat.MEDIUM , DateFormat.LONG , DateFormat.FULL . The exact result depends on the locale, but generally ,

  • SHORT is completely numeric, such as 7/24/98 (for date) and 4:49 PM (for time).

  • MEDIUM is longer, such as 24-Jul-98 (for date) and 4:52:09 PM (for time).

  • LONG is even longer, such as July 24, 1998 (for date) and 4:53:16 PM EST (for time).

  • FULL is completely specified, such as Friday, July 24, 1998 (for date) and 4:54:13 o'clock PM EST (for time).

The statements given below display current time with a specified time zone (CST), formatting style (full date and full time), and locale (US).

 GregorianCalendar calendar =   new   GregorianCalendar(); DateFormat formatter = DateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, Locale.US); TimeZone timeZone = TimeZone.getTimeZone(   "CST"   ); formatter.setTimeZone(timeZone); System.out.println(   "The local time is "   + formatter.format(calendar.getTime())); 

26.3.3. The SimpleDateFormat Class

The date and time formatting subclass, SimpleDateFormat , enables you to choose any user-defined pattern for date and time formatting. The constructor shown below can be used to create a SimpleDateFormat object, and the object can be used to convert a Date object into a string with the desired format.

   public   SimpleDateFormat(String pattern) 


[Page 866]

The parameter pattern is a string consisting of characters with special meanings. For example, y means year, M means month, d means day of the month, G is for era designator, h means hour , m means minute of the hour, s means second of the minute, and z means time zone. Therefore, the following code will display a string like "Current time is 1997.11.12 AD at 04:10:18 PST" because the pattern is "yyyy.MM.dd G 'at' hh:mm:ss z":

 SimpleDateFormat formatter =   new   SimpleDateFormat(   "yyyy.MM.dd G 'at' hh:mm:ss z"   ); date currentTime =   new   Date(); String dateString = formatter.format(currentTime); System.out.println(   "Current time is "   + dateString); 

26.3.4. The DateFormatSymbols Class

The DateFormatSymbols class encapsulates localizable date-time formatting data, such as the names of the months, and the names of the days of the week, as shown in Figure 26.3.

Figure 26.3. The DateFormatSymbols class encapsulates localizable date-time formatting data.

For example, the following statement displays the month names and weekday names for the default locale:

 DateFormatSymbols symbols =   new   DateFormatSymbols(); String[] monthNames = symbols.getMonths();   for   (   int   i = 0; i < monthNames.length; i++) { System.out.println(monthNames[i]); } String[] weekdayNames = symbols.getWeekdays();   for   (   int   i =     ; i < weekdayNames.length; i++) { System.out.println(weekdayNames[i]); } 

The following two examples demonstrate how to display date, time, and calendar based on locale. The first example creates a clock and displays date and time in locale-sensitive format. The second example displays several different calendars with the names of the days shown in the appropriate local language.


[Page 867]

26.3.5. Example: Displaying an International Clock

Write a program that displays a clock to show the current time based on the specified locale and time zone. The locale and time zone are selected from the combo boxes that contain the available locales and time zones in the system, as shown in Figure 26.4.

Figure 26.4. The program displays a clock that shows the current time with the specified locale and time zone.

Here are the major steps in the program:

  1. Create a subclass of JPanel named WorldClock (Listing 26.1) to contain an instance of the StillClock class (developed in §13.12, "Case Study: The StillClock Class"), and place it in the center. Create a JLabel to display the digit time, and place it in the south. Use the GreogorianCalendar class to obtain the current time for a specific locale and time zone.

  2. Create a subclass of JPanel named WorldClockControl (Listing 26.2) to contain an instance of WorldClock and two instances of JComboBox for selecting locales and time zones.

  3. Create an applet named WorldClockApp (Listing 26.3) to contain an instance of WorldClockControl and enable the applet to run standalone.

The relationship among these classes is shown in Figure 26.5.

Figure 26.5. WorldClockApp contains WorldClockControl , and WorldClockControl contains WorldClock .

Listing 26.1. WorldClock.java
(This item is displayed on pages 867 - 868 in the print version)
 1   import   javax.swing.*; 2   import   java.awt.*; 3   import   java.awt.event.*; 

[Page 868]
 4   import   java.util.Calendar; 5   import   java.util.TimeZone; 6   import   java.util.GregorianCalendar; 7   import   java.text.*; 8 9   public class   WorldClock   extends   JPanel { 10   private   TimeZone timeZone = TimeZone.getTimeZone(   "EST"   ); 11    private   Timer timer =   new   Timer(   1000   ,   new   TimerListener());  12    private   StillClock clock =   new   StillClock();  13   private   JLabel jlblDigitTime =   new   JLabel(   ""   , JLabel.CENTER); 14 15    public   WorldClock()  { 16 setLayout(   new   BorderLayout()); 17 add(clock, BorderLayout.CENTER); 18 add(jlblDigitTime, BorderLayout.SOUTH); 19  timer.start();  20 } 21 22   public void   setTimeZone(TimeZone timeZone) { 23   this   .timeZone = timeZone; 24 } 25 26    private class  TimerListener   implements   ActionListener {   27   public void   actionPerformed(ActionEvent e) { 28  Calendar calendar =   new   GregorianCalendar(timeZone, getLocale());  29 clock.setHour(calendar.get(Calendar.HOUR)); 30 clock.setMinute(calendar.get(Calendar.MINUTE)); 31 clock.setSecond(calendar.get(Calendar.SECOND)); 32 33  // Display digit time on the label  34  DateFormat formatter = DateFormat.getDateTimeInstance  35  (DateFormat.MEDIUM, DateFormat.LONG, getLocale());  36  formatter.setTimeZone(timeZone);  37 jlblDigitTime.setText(  formatter.format(calendar.getTime())  ); 38 } 39 } 40 } 

Listing 26.2. WorldClockControl.java
(This item is displayed on pages 868 - 869 in the print version)
 1   import   javax.swing.*; 2   import   java.awt.*; 3   import   java.awt.event.*; 4   import   java.util.*; 5 6   public class   WorldClockControl   extends   JPanel { 7  // Obtain all available locales and time zone ids  8   private   Locale[] availableLocales = Locale.getAvailableLocales(); 9   private   String[] availableTimeZones = TimeZone.getAvailableIDs(); 10 11  // Comboxes to display available locales and time zones  12   private   JComboBox jcbLocales =   new   JComboBox(); 13   private   JComboBox jcbTimeZones =   new   JComboBox(); 14 15  // Create a clock  16    private  WorldClock clock =   new   WorldClock();   17 18    public   WorldClockControl()  { 

[Page 869]
 19  // Initialize jcbLocales with all available locales  20 setAvailableLocales(); 21 22  // Initialize jcbTimeZones with all available time zones  23 setAvailableTimeZones(); 24 25  // Initialize locale and time zone  26  clock.setLocale(  27  availableLocales[jcbLocales.getSelectedIndex()]);  28  clock.setTimeZone(TimeZone.getTimeZone(  29  availableTimeZones[jcbTimeZones.getSelectedIndex()]));  30 31 JPanel panel1 =   new   JPanel(); 32 panel1.setLayout(   new   GridLayout(   2   ,   1   )); 33 panel1.add(   new   JLabel(   "Locale"   )); 34 panel1.add(   new   JLabel(   "Time Zone"   )); 35 JPanel panel2 =   new   JPanel(); 36 37 panel2.setLayout(   new   GridLayout(   2   ,   1   )); 38 panel2.add(jcbLocales, BorderLayout.CENTER); 39 panel2.add(jcbTimeZones, BorderLayout.CENTER); 40 41 JPanel panel3 =   new   JPanel(); 42 panel3.setLayout(   new   BorderLayout()); 43 panel3.add(panel1, BorderLayout.WEST); 44 panel3.add(panel2, BorderLayout.CENTER); 45 46 setLayout(   new   BorderLayout()); 47 add(panel3, BorderLayout.NORTH); 48 add(clock, BorderLayout.CENTER); 49 50  jcbLocales.addActionListener(   new   ActionListener() {  51   public void   actionPerformed(ActionEvent e) { 52 clock.setLocale( 53 availableLocales[jcbLocales.getSelectedIndex()]); 54 } 55 }); 56  jcbTimeZones.addActionListener(   new   ActionListener() {  57   public void   actionPerformed(ActionEvent e) { 58 clock.setTimeZone(TimeZone.getTimeZone( 59 availableTimeZones[jcbTimeZones.getSelectedIndex()])); 60 } 61 }); 62 } 63 64   private void   setAvailableLocales() { 65   for   (   int   i =     ; i < availableLocales.length; i++) { 66 jcbLocales.addItem(availableLocales[i].getDisplayName() +   " "   67 + availableLocales[i].toString()); 68 } 69 } 70 71   private void   setAvailableTimeZones() { 72  // Sort time zones  73 Arrays.sort(availableTimeZones); 74   for   (   int   i =     ; i < availableTimeZones.length; i++) { 75 jcbTimeZones.addItem(availableTimeZones[i]); 76 } 77 } 78 } 


[Page 870]
Listing 26.3. WorldClockApp.java
 1   import   javax.swing.*; 2 3   public class   WorldClockApp   extends   JApplet { 4  /** Construct the applet */  5   public   WorldClockApp() { 6 add(   new   WorldClockControl()); 7 } 8 } 

The WorldClock class uses GregorianCalendar to obtain a Calendar object for the specified locale and time zone (line 28). Since WorldClock extends JPanel , and every GUI component has the locale property, the locale for the calendar is obtained from the WorldClock using getLocale() (line 35).

An instance of StillClock is created (line 12) and placed in the panel (line 17). The clock time is updated every one second using the current Calendar object in lines 28 “31.

An instance of DateFormat is created (lines 34 “35) and is used to format the date in accordance with the locale (line 37).

The WorldClockControl class contains an instance of WorldClock and two combo boxes. The combo boxes store all the available locales and time zones (lines 64 “77). The newly selected locale and time zone are set in the clock (lines 56 “61) and used to display a new time based on the current locale and time zone.

26.3.6. Example: Displaying a Calendar

Write a program that displays a calendar based on the specified locale, as shown in Figure 26.6. The user can specify a locale from a combo box that consists of a list of all the available locales supported by the system. When the program starts, the calendar for the current month of the year is displayed. The user can use the Prior and Next buttons to browse the calendar.

Figure 26.6. The calendar applet displays a calendar with a specified locale.

Here are the major steps in the program:

  1. Create a subclass of JPanel named CalendarPanel (Listing 26.4) to display the calendar for the given year and month based on the specified locale and time zone.

  2. Create an applet named CalendarApp (Listing 26.5). Create a panel to hold an instance of CalendarPanel and two buttons, Prior and Next . Place the panel in the center of the applet. Create a combo box and place it in the south of the applet. The relationships among these classes are shown in Figure 26.7.


[Page 871]
Figure 26.7. CalendarApp contains CalendarPanel .

Listing 26.4. CalendarPanel.java
(This item is displayed on pages 871 - 873 in the print version)
 1   import   java.awt.*; 2   import   javax.swing.*; 3   import   javax.swing.border.LineBorder; 4   import   java.util.*; 5   import   java.text.*; 6 7   public class   CalendarPanel  extends  JPanel { 8  // The header label  9   private   JLabel jlblHeader =   new   JLabel(   " "   , JLabel.CENTER); 10 11  // Labels to display day names and days  12   private   JLabel[] jlblDay =   new   JLabel[   49   ]; 13 14   private   Calendar calendar; 15   private int   month;  // The specified month  16   private int   year;  // The specified year  17 18    public   CalendarPanel()  { 19  // Panel jpDays to hold day names and days  20 JPanel jpDays =   new   JPanel(); 21 jpDays.setLayout(   new   GridLayout(   7   ,   1   )); 22   for   (   int   i =     ; i <   49   ; i++) { 23 jpDays.add(jlblDay[i] =   new   JLabel()); 24 jlblDay[i].setBorder(   new   LineBorder(Color.black,   1   )); 25 jlblDay[i].setHorizontalAlignment(JLabel.RIGHT); 26 jlblDay[i].setVerticalAlignment(JLabel.TOP); 27 } 28 29  // Place header and calendar body in the panel  30   this   .setLayout(   new   BorderLayout()); 31   this   .add(jlblHeader, BorderLayout.NORTH); 32   this   .add(jpDays, BorderLayout.CENTER); 33 

[Page 872]
 34  // Set current month, and year  35  calendar =   new   GregorianCalendar();  36  month = calendar.get(Calendar.MONTH) +   1   ;  37  year = calendar.get(Calendar.YEAR);  38 39  // Show calendar  40 showHeader(); 41 showDayNames(); 42 showDays(); 43 } 44 45  /** Update the header based on locale */  46   private void   showHeader() { 47  SimpleDateFormat sdf =  48    new   SimpleDateFormat(   "MMMM yyyy"   , getLocale());  49  String header = sdf.format(calendar.getTime());  50 jlblHeader.setText(header); 51 } 52 53  /** Update the day names based on locale */  54   private void   showDayNames() { 55  DateFormatSymbols dfs =   new   DateFormatSymbols(getLocale());  56  String dayNames[] = dfs.getWeekdays();  57 58  // Set calendar days  59   for   (   int   i =     ; i <   7   ; i++) { 60 jlblDay[i].setText(dayNames[i +   1   ]); 61 jlblDay[i].setHorizontalAlignment(JLabel.CENTER); 62 } 63 } 64 65  /** Display days */  66   public void   showDays() { 67  // Set the calendar to the first day of the  68  // specified month and year  69  calendar.set(Calendar.YEAR, year);  70  calendar.set(Calendar.MONTH, month -   1   );  71  calendar.set(Calendar.DATE,   1   );  72 73  // Get the day of the first day in a month  74   int   startingDayOfMonth =  calendar.get(Calendar.DAY_OF_WEEK)  ; 75 76  // Fill the calendar with the days before this month  77  Calendar cloneCalendar = (Calendar)calendar.clone();  78 cloneCalendar.add(Calendar.DATE,   -1   ); 79   int   daysInMonth = cloneCalendar.getActualMaximum( 80 Calendar.DAY_OF_MONTH); 81 82   for   (   int   i =     ; i < startingDayOfMonth -   1   ; i++) { 83 jlblDay[i +   7   ].setForeground(Color.yellow); 84 jlblDay[i +   7   ].setText(daysInMonth - 85 startingDayOfMonth +   2   + i +   ""   ); 86 } 87 88  // Display days of this month  89   for   (   int   i =   1   ; i <= daysInMonth; i++) { 90 jlblDay[i -   2   + startingDayOfMonth +   7   ]. 91 setForeground(Color.black); 92 jlblDay[i -   2   + startingDayOfMonth +   7   ].setText(i +   ""   ); 93 } 

[Page 873]
 94 95  // Fill the calendar with the days after this month  96   int   j =   1   ; 97   for   (   int   i = daysInMonth -   1   + startingDayOfMonth +   7   ; 98 i <   49   ; i++) { 99 jlblDay[i].setForeground(Color.yellow); 100 jlblDay[i].setText(j++ +   ""   ); 101 } 102 103 showHeader(); 104 } 105 106  /** Return month */  107   public int   getMonth() { 108   return   month; 109 } 110 111  /** Set a new month */  112   public void   setMonth(   int   newMonth) { 113 month = newMonth; 114 showDays(); 115 } 116 117  /** Return year */  118   public int   getYear() { 119   return   year; 120 } 121 122  /** Set a new year */  123   public void   setYear(   int   newYear) { 124 year = newYear; 125 showDays(); 126 } 127 128  /** Set a new locale */  129   public void   changeLocale(Locale newLocale) { 130 setLocale(newLocale); 131 showHeader(); 132 showDayNames(); 133 } 134 } 

CalendarPanel is created to control and display the calendar. It displays the month and year in the header, and the day names and days in the calendar body. The header and day names are locale-sensitive.

The showHeader method (lines 46 “51) displays the calendar title in a form like "MMMM yyyy". The SimpleDateFormat class used in the showHeader method is a subclass of DateFormat . SimpleDateFormat allows you to customize the date format to display the date in various nonstandard styles.

The showDayNames method (lines 54 “63) displays the day names in the calendar. The DateFormatSymbols class used in the showDayNames method is a class for encapsulating localizable date-time formatting data, such as the names of the months, the names of the days of the week, and the time zone data. The getWeekdays method is used to get an array of day names.

The showDays method (lines 66 “104) displays the days for the specified month of the year. As you can see in Figure 26.6, the labels before the current month are filled with the last few days of the preceding month, and the labels after the current month are filled with the first few days of the next month.


[Page 874]

To fill the calendar with the days before the current month, a clone of calendar , named cloneCalendar , is created to obtain the days for the preceding month (line 77). cloneCalendar is a copy of calendar with separate memory space. Thus you can change the properties of cloneCalendar without corrupting the calendar object. The clone() method is defined in the Object class, which was introduced in §9.13.4, "The clone Method." You can clone any object as long as its defining class implements the Cloneable interface. The Calendar class implements Cloneable .

The cloneCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) method (lines 79 “80) returns the number of days in the month for the specified calendar.

Listing 26.5. CalendarApp.java
(This item is displayed on pages 874 - 875 in the print version)
 1   import   java.awt.*; 2   import   java.awt.event.*; 3   import   javax.swing.*; 4   import   javax.swing.border.*; 5   import   java.util.*; 6 7   public class   CalendarApp   extends   JApplet { 8  // Create a CalendarPanel for showing calendars  9    private   CalendarPanel calendarPanel =   new   CalendarPanel();  10 11  // Combo box for selecting available locales  12   private   JComboBox jcboLocale =   new   JComboBox(); 13 14  // Declare locales to store available locales  15    private   Locale locales[] = Calendar.getAvailableLocales();  16 17  // Buttons Prior and Next to displaying prior and next month  18   private   JButton jbtPrior =   new   JButton(   "Prior"   ); 19   private   JButton jbtNext =   new   JButton(   "Next"   ); 20 21  /** Initialize the applet */  22   public void   init() { 23  // Panel jpLocale to hold the combo box for selecting locales  24 JPanel jpLocale =   new   JPanel(); 25 jpLocale.setBorder(   new   TitledBorder(   "Choose a locale"   )); 26 jpLocale.setLayout(   new   FlowLayout()); 27 jpLocale.add(jcboLocale); 28 29  // Initialize the combo box to add locale names  30   for   (   int   i =     ; i < locales.length; i++) 31 jcboLocale.addItem(locales[i].getDisplayName()); 32 33  // Panel jpButtons to hold buttons  34 JPanel jpButtons =   new   JPanel(); 35 jpButtons.setLayout(   new   FlowLayout()); 36 jpButtons.add(jbtPrior); 37 jpButtons.add(jbtNext); 38 39  // Panel jpCalendar to hold calendarPanel and buttons  40 JPanel jpCalendar =   new   JPanel(); 41 jpCalendar.setLayout(   new   BorderLayout()); 42 jpCalendar.add(calendarPanel, BorderLayout.CENTER); 43 jpCalendar.add(jpButtons, BorderLayout.SOUTH); 44 45  // Place jpCalendar and jpLocale to the applet  46 add(jpCalendar, BorderLayout.CENTER); 47 add(jpLocale, BorderLayout.SOUTH); 

[Page 875]
 48 49  // Register listeners  50  jcboLocale.addActionListener(new ActionListener() {  51   public void   actionPerformed(ActionEvent e) { 52   if   (e.getSource() == jcboLocale) 53 calendarPanel.changeLocale( 54 locales[jcboLocale.getSelectedIndex()]); 55 } 56 }); 57 58  jbtPrior.addActionListener(   new   ActionListener() {  59   public void   actionPerformed(ActionEvent e) { 60   int   currentMonth = calendarPanel.getMonth(); 61   if   (currentMonth ==   1   ) { 62 calendarPanel.setMonth(   12   ); 63 calendarPanel.setYear(calendarPanel.getYear() -   1   ); 64 } 65   else   66 calendarPanel.setMonth(currentMonth -   1   ); 67 } 68 }); 69 70  jbtNext.addActionListener(   new   ActionListener() {  71   public void   actionPerformed(ActionEvent e) { 72   int   currentMonth = calendarPanel.getMonth(); 73   if   (currentMonth ==   12   ) { 74 calendarPanel.setMonth(   1   ); 75 calendarPanel.setYear(calendarPanel.getYear() +   1   ); 76 } 77   else   78 calendarPanel.setMonth(currentMonth +   1   ); 79 } 80 }); 81 82 calendarPanel.changeLocale( 83 locales[jcboLocale.getSelectedIndex()]); 84 } 85 } 

CalendarApp creates the user interface and handles the button actions and combo box item selections for locales. The Calendar.getAvailableLocales() method (line 15) is used to find all the available locales that have calendars. Its getDisplayName() method returns the name of each locale and adds the name to the combo box (line 31). When the user selects a locale name in the combo box, a new locale is passed to calendarPanel , and a new calendar is displayed based on the new locale (lines 53 “54).

 


Introduction to Java Programming-Comprehensive Version
Introduction to Java Programming-Comprehensive Version (6th Edition)
ISBN: B000ONFLUM
EAN: N/A
Year: 2004
Pages: 503

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