Parsing and displaying dates and times is often complicated because of formatting and locale issues. Java 2 Platform, Standard Edition (J2SE) provides several classes to simplify date and time handling -- classes such as java.util.Calendar
, java.util.Date
, java.util.TimeZone
, and java.text.DateFormat
. By comparison, the Mobile Information Device Profile (MIDP) defines only subsets of the Calendar
, Date
and TimeZone
classes, and does not include any form of DateFormat
. How, then, can your MIDP applications properly handle dates and times?
The answer lies in the javax.microedition.lcdui.DateField
class, part of the MIDP high-level user interface API. DateField
is an interactive user interface component that displays a date, time, or both. It also allows you to edit the date and time. DateField
extends the Item
class. This means that DateField
components can be placed on Form
objects. So the first step in using a DateField
is to create a Form
and place the DateField
on the form:
Form f = new Form( "A Form" );
f.append( df );
As with any Item, the DateField
is displayed only when the form is made active by calling Display.setCurrent
.
The DateField
class defines two constructors:
public DateField( String label, int mode );
public DateField( String label, int mode,
java.util.TimeZone zone );
To properly display dates and times, a DateField
instance needs to know which time zone to use. The two-argument constructor uses the device's default time zone. The three-argument constructor lets you specify an explicit time zone if the default is inappropriate. Note that you can't change the displayed time zone without creating a new instance of DateField
.
The first two arguments are identical in both constructors. The first argument is the label to display alongside the field -- use null if there is no label. The second argument is the input mode of the field. There are three possible modes, these are declared as constants in the DateField
class:
public static final int DATE = 1;
public static final int TIME = 2;
public static final int DATE_TIME = 3;
The input mode controls what the field displays: a date only, a time only, or a combined date and a time. You can change the input mode at any time by calling the setInputMode
method.
When you create a new DateField
instance, you do not have to set a date or time. The following code, for example, displays an uninitialized date:
Display display = ....; // initialized elsewhere |
To initialize the field to a particular date or time, call setDate
and pass in a java.util.Date
object initialized to the correct value:
Calendar c = Calendar.getInstance();
c.set( Calendar.MONTH, Calendar.OCTOBER );
c.set( Calendar.DAY_OF_MONTH, 18 );
c.set( Calendar.YEAR, 1996 );
c.set( Calendar.HOUR_OF_DAY, 16 );
c.set( Calendar.MINUTE, 39 );
c.set( Calendar.SECOND, 45 );
c.set( Calendar.MILLISECOND, 0 );
Date moment = c.getTime();
DateField df = new DateField( null,
DateField.DATE_TIME );
df.setTime( moment );
A Date
object represents a moment in time (in coordinated universal time, or UTC, to be exact) as the number of milliseconds since midnight, January 1, 1970. Use a Calendar
instance to create a Date
instance, as shown above.
Note that a DateField
in TIME
input mode requires the date portion to be set to January 1, 1970. Two useful routines for clearing out the date portion of a Date
and for combining two Date
objects into a single object are as follows:
// Return a Date with the time intact but the date |
Always do your date manipulation using the Calendar
class, not using the raw milliseconds value stored in a Date
object.
After a DateField
is displayed, the system will allow the user to select the object and edit the date, time or both, depending on the input mode. Whenever you need to obtain the new date/time, call the getDate
method:
Here is a simple MIDlet
that lets you view and edit dates and times using all three input modes.
import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
/**
* Demonstration of time/date editing using the MIDP
* DateField class.
*/
public class DateFieldTest extends MIDlet {
private Display display;
// Define our Command objects
private Command exitCommand =
new Command( "Exit", Command.EXIT, 1 );
private Command okCommand =
new Command( "OK", Command.OK, 1 );
private Command cancelCommand =
new Command(
"Cancel", Command.CANCEL, 1 );
public DateFieldTest(){
}
protected void destroyApp( boolean unconditional )
throws MIDletStateChangeException {
exitMIDlet();
}
protected void pauseApp(){
}
protected void startApp()
throws MIDletStateChangeException {
if( display == null ){ // first time called...
initMIDlet();
}
}
private void initMIDlet(){
display = Display.getDisplay( this );
testList = new TestList();
display.setCurrent( testList );
}
public void exitMIDlet(){
notifyDestroyed();
}
// Return a Date with the time intact but the date
// set to January 1, 1970
public static Date clearDate( Date d ){
Calendar c = Calendar.getInstance();
c.setTime( d );
c.set( Calendar.MONTH, Calendar.JANUARY );
c.set( Calendar.DAY_OF_MONTH, 1 );
c.set( Calendar.YEAR, 1970 );
return c.getTime();
}
// Combine a date and time into a single
// Date instance
public static Date combineDateTime( Date date,
Date time ){
Calendar cd = Calendar.getInstance();
Calendar ct = Calendar.getInstance();
cd.setTime( date );
ct.setTime( time );
ct.set( Calendar.MONTH,
cd.get( Calendar.MONTH ) );
ct.set( Calendar.DAY_OF_MONTH,
cd.get( Calendar.DAY_OF_MONTH ) );
ct.set( Calendar.YEAR,
cd.get( Calendar.YEAR ) );
return ct.getTime();
}
// The list of tests we can perform, arranged
// in threes so that ( index % 3 ) == one
// of DATE, TIME or DATE_TIME
static final String[] testLabels = {
"Current date",
"Current time",
"Current date/time",
"Edit date",
"Edit time",
"Edit date/time",
};
private TestList testList;
private Date editDate;
//
// Displays the list of actions
//
class TestList extends List
implements CommandListener {
public TestList(){
super( "DateField Tests", IMPLICIT,
testLabels, null );
addCommand( exitCommand );
setCommandListener( this );
}
public void commandAction( Command c,
Displayable d ){
if( c == exitCommand ){
exitMIDlet();
} else if( c == List.SELECT_COMMAND ){
// Figure out which date to display
// and what the input mode is
int which = getSelectedIndex();
String label = getString( which );
int mode = ( which % 3 ) + 1;
boolean save = ( which > 2 );
display.setCurrent(
new Edit( save, label, mode ) );
}
}
}
//
// Edit a date, time or date/time, optionally
// saving the value.
//
class Edit extends Form
implements CommandListener {
public Edit( boolean save, String label,
int mode ){
super( label );
this.save = save;
Date d = editDate;
if( !save ){
d = new Date();
}
dateField = new DateField( null, mode );
append( dateField );
if( d != null ){
if( mode == DateField.TIME ){
d = clearDate( d );
}
dateField.setDate( d );
}
addCommand( okCommand );
if( save ){
addCommand( cancelCommand );
}
setCommandListener( this );
}
public void commandAction( Command c,
Displayable d ){
Alert alert = null;
Date date = dateField.getDate();
if(
save && date != null && c == okCommand ){
if( editDate != null ){
int mode = dateField.getInputMode();
if( mode == DateField.DATE ){
editDate = combineDateTime(
date, editDate );
} else if(
mode == DateField.TIME ){
editDate = combineDateTime(
editDate, date );
} else {
editDate = date;
}
} else {
editDate = date;
}
Calendar cal = Calendar.getInstance();
cal.setTime( editDate );
alert = new Alert( "New date/time" );
alert.setString(
"The saved date/time is now " + cal );
alert.setTimeout( Alert.FOREVER );
}
if( alert != null ){
display.setCurrent( alert, testList );
} else {
display.setCurrent( testList );
}
}
private DateField dateField;
private boolean save;
}
}
No comments:
Post a Comment