/*
 * @(#)DateTimeDemo.java	 1.1 98/06/16
 *
 * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
 * (C) Copyright IBM Corp. 1996 - All Rights Reserved
 *
 * Portions copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
 *
 *   The original version of this source code and documentation is copyrighted
 * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
 * materials are provided under terms of a License Agreement between Taligent
 * and Sun. This technology is protected by multiple US and International
 * patents. This notice and attribution to Taligent may not be removed.
 *   Taligent is a registered trademark of Taligent, Inc.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies. Please refer to the file "copyright.html"
 * for further important copyright and licensing information.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *
 */

import java.applet.Applet;
import java.awt.event.*;
import java.awt.*;
import java.lang.*;
import java.util.*;
import java.net.*;
import java.io.*;
import java.text.*;


/**
 * DateTimeDemo demonstrates how Date/Time formatter works. 
 */
public class DateTimeDemo extends DemoApplet
{
    /**
     * The main function which defines the behavior of the DateTimeDemo
     * applet when an applet is started.
     */
    public static void main(String argv[]) {
        DemoApplet.showDemo(new DateTimeFrame(null));
    }

    /**
     * This creates a DateTimeFrame for the demo applet.
     */
    public Frame createDemoFrame(DemoApplet applet) {
        return new DateTimeFrame(applet);
    }
}

/**
 * A Frame is a top-level window with a title. The default layout for a frame
 * is BorderLayout.  The DateTimeFrame class defines the window layout of
 * DateTimeDemo.
 */
class DateTimeFrame extends Frame implements WindowListener, ActionListener, ItemListener, KeyListener
{
    private static final String creditString
        = "";
    private static final String copyrightString
        = "";
    private static final String copyrightString2
        = "";

    private static final int FIELD_COLUMNS = 45;

    private static final boolean DEBUG = false;

    private static final int millisPerHour = 60 * 60 * 1000;
    private boolean isLocalized = false;
    private boolean validationMode = false;
    private Locale curLocale = Locale.US;

    private SimpleDateFormat format;
    private Locale[] locales;
    private DemoApplet applet;

    // Mapping tables for displaying Rep. Cities for given timezones.
    private static final int kAdjCityIndex[]
    // many-to-1 mapping:
    // locale index --> rep city index
    = { 1,
        3,
        2,
        4,
        0,
        5,  // eg, Locale Index: 5 --> Rep. City index: 5
	0,
	0,
        6};

    private static final int kZoneOffsets[]
    // 1-to-1 maping:
    // kZoneOffsets returns the zone offset for a given rep. city index.
    = { 1*millisPerHour,
       -8*millisPerHour,
                      0,
       -5*millisPerHour,
       -7*millisPerHour,
       -6*millisPerHour,
        9*millisPerHour};

    private static final String kZoneIDs[]
    // 1-1 maping:
    // kZoneIDs returns the zone ID string for a given rep. city index.
    = {"ECT",
       "PST",
       "GMT",
       "EST",
       "MST",
       "CST",
       "JST"};


    /**
     * Constructs a new DateTimeFrame that is initially invisible.
     */
    public DateTimeFrame(DemoApplet applet)
    {
        super("Date/Time Formatting Demo");
        this.applet = applet;
	addWindowListener(this);
        init();
        start();
    }


    /**
     * Initializes the applet. You never need to call this directly, it
     * is called automatically by the system once the applet is created.
     */
    public void init()
    {
        // Get G7 locales only for demo purpose. To get all the locales
        // supported, switch to calling TimeFormat.getAvailableLocales().
        // commented.  However, the mapping tables such as kAdjCityIndex
        // must be expended as well.
        locales = Utility.getG7Locales();
//        locales = TimeFormat.getAvailableLocales();

        buildGUI();

        // Stick the names of the locales into the locale popup menu
        Locale displayLocale = Locale.getDefault();
        for (int i = 0; i < locales.length; i++) {
            if (locales[i].getCountry().length() > 0) {
                localeMenu.addItem( locales[i].getDisplayName() );
                if (locales[i].equals(Locale.getDefault())) {
                    localeMenu.select(i);
                }
            }
        }

        // For starters, use the default format for the selected locale
        // in the menu
        setFormatFromLocale(true);
        formatText();
    }

    //------------------------------------------------------------
    // package private
    //------------------------------------------------------------
    void addWithFont(Container container, Component foo, Font font) {
        if (font != null)
            foo.setFont(font);
        container.add(foo);
    }

    /**
     * Called to start the applet. You never need to call this method
     * directly, it is called when the applet's document is visited.
     */
    public void start()
    {
        // do nothing
    }

    /**
     * This function is called when it is necessary to display a new
     * format pattern. This happens when the state of the "Localized Pattern"
     * CheckBox is changed.
     */
    public void handleNewFormat()
    {
        Utility.setText(patternText, format.toPattern() );
    }

    /**
     * This function is called when users change the Calendar (time fields)
     * validation mode. When the state of the "Validation Mode" CheckBox
     * is changed, the time string in the "New Date" text field will be
     * re-parsed, and the parsing result will be displayed in the "1.0 Date"
     * text field.
     */
    public void validationModeChanged()
    {
        format.setLenient(validationMode);

        parseText();
    }

    //{{DECLARE_CONTROLS
    Panel localePanel;
    Panel formatPanel;
    CheckboxGroup group1;
    CheckboxGroup group2;
    Label label1;
    Label label2;
    Label label3;
    Label demo;
    Label code;
    Choice localeMenu;
    Choice dateStyleMenu;
    Choice timeStyleMenu;
    Choice dateMenu;
    Choice cityMenu;
    Label dateLabel;
    Label cityLabel;
    TextField millisText;
    Label millisLabel;
    Button up;
    Button down;
    Label localeLabel;
    Label dateStyleLabel;
    Label timeStyleLabel;
    TextField inputText;
    TextField outputText;
    Label formatLabel;
    Label parseLabel;
    //Button rightButton;
    //Button leftButton;
    TextField patternText;
    Label label4;
    Checkbox getDateInstance;
    Checkbox getTimeInstance;
    Checkbox getDateTimeInstance;
    Checkbox getRoll;
    Checkbox getAdd;
    Checkbox getLocalized;
    Checkbox getValidationMode;

    //}}

    Color color = Color.white;
    public void buildGUI()
    {
        //{{INIT_CONTROLS

        setBackground(color);
        setLayout(new FlowLayout()); // shouldn't be necessary, but it is.

// TITLE
        Panel titlePanel = new Panel();


        label1=new Label("Date/Time Formatting Demo", Label.CENTER);
        label1.setFont(Utility.titleFont);

        titlePanel.add(label1);

// CREDITS

        Panel creditPanel = new Panel();

        demo=new Label(creditString, Label.CENTER);
        demo.setFont(Utility.creditFont);
        creditPanel.add(demo);

        titlePanel.add(creditPanel);

        Utility.fixGrid(titlePanel,1);
         add(titlePanel);


// IO Panel
        Panel topPanel = new Panel();
        topPanel.setLayout(new FlowLayout());

        label3=new Label("New Date", Label.RIGHT);
        label3.setFont(Utility.labelFont);
        topPanel.add(label3);

        outputText=new TextField(FIELD_COLUMNS);
	outputText.addKeyListener(this);
        outputText.setFont(Utility.editFont);
        topPanel.add(outputText);


        label2=new Label("1.0 Date", Label.RIGHT);
        label2.setFont(Utility.labelFont);
        topPanel.add(label2);

	// intentional use of deprecated method
        inputText=new TextField(new Date().toGMTString(),FIELD_COLUMNS);
	inputText.addKeyListener(this);
        inputText.setFont(Utility.editFont);
        topPanel.add(inputText);


        millisLabel=new Label("Millis", Label.RIGHT);
        millisLabel.setFont(Utility.labelFont);
        topPanel.add(millisLabel);

        millisText=new TextField(FIELD_COLUMNS);
	millisText.addKeyListener(this);
        millisText.setFont(Utility.editFont);
        topPanel.add(millisText);

        label4=new Label("Pattern", Label.RIGHT);
        label4.setFont(Utility.labelFont);
        topPanel.add(label4);

        patternText=new TextField(FIELD_COLUMNS);
	patternText.addKeyListener(this);
        patternText.setFont(Utility.editFont);
        topPanel.add(patternText);

        topPanel.add(new Label(" "));

        getLocalized=new Checkbox("Localized Pattern");
	getLocalized.addItemListener(this);
        getLocalized.setFont(Utility.labelFont);

        getValidationMode=new Checkbox("Validation Mode");
	getValidationMode.addItemListener(this);
        getValidationMode.setFont(Utility.labelFont);

        Panel checkBoxesPanel = new Panel();
        checkBoxesPanel.setLayout(new GridLayout(1,2,40,0));
        checkBoxesPanel.add(getLocalized);
        checkBoxesPanel.add(getValidationMode);

        topPanel.add(checkBoxesPanel);

        Utility.fixGrid(topPanel,2);
         add(topPanel);

// DATE

        Panel datePanel=new Panel();
        datePanel.setLayout(new FlowLayout());

        group2= new CheckboxGroup();

        getRoll=new Checkbox("Roll",group2, true);
        getAdd=new Checkbox("Add",group2, false);
	getRoll.addItemListener(this);
	getAdd.addItemListener(this);

        dateLabel=new Label("Date Fields");
        dateLabel.setFont(Utility.labelFont);

        Panel upDown = new Panel();
        upDown.setLayout(new GridLayout(2,1));

        // *** If the images are not found, we use the label.
        up = new Button("^");
        down = new Button("v");
	up.addActionListener(this);
	down.addActionListener(this);
        up.setBackground(Color.lightGray);
        down.setBackground(Color.lightGray);
        upDown.add(up);
        upDown.add(down);


        Panel rollAddBoxes = new Panel();
        rollAddBoxes.setLayout(new GridLayout(2,1));

        rollAddBoxes.add(getRoll);
        rollAddBoxes.add(getAdd);

        Panel rollAddPanel = new Panel();
        rollAddPanel.setLayout(new FlowLayout());
        rollAddPanel.add(rollAddBoxes);
        rollAddPanel.add(upDown);

        dateMenu= new Choice();
        dateMenu.addItem( "Year");
        dateMenu.addItem( "Month");
        dateMenu.addItem( "Day of Month");
        dateMenu.addItem( "Hour of Day");
        dateMenu.addItem( "Minute");
        dateMenu.addItem( "Second");
        dateMenu.addItem( "Millisecond");

        Panel dateLM = new Panel();
        dateLM.setLayout(new GridLayout(2,1));
        dateLM.add(dateLabel);
        dateLM.add(dateMenu);

        datePanel.add(dateLM);

// CITIES

        Panel citiesPanel=new Panel();
        citiesPanel.setLayout(new FlowLayout());
        Panel cityPanel=new Panel();
        cityPanel.setLayout(new GridLayout(2,1));
        cityMenu= new Choice();
	cityMenu.addItemListener(this);
        cityMenu.addItem( "Paris");
        cityMenu.addItem( "Copenhagen");
        cityMenu.addItem( "London");
        cityMenu.addItem( "Washington");
        cityMenu.addItem( "Toronto");
        cityMenu.addItem( "Montreal");
        cityMenu.addItem( "Tokyo");

        cityLabel=new Label("City");
        cityLabel.setFont(Utility.labelFont);

        cityPanel.add(cityLabel);
        cityPanel.add(cityMenu);
        citiesPanel.add(cityPanel);

        Panel cityDatePanel = new Panel();
        cityDatePanel.add(citiesPanel);
        cityDatePanel.add(datePanel);
        cityDatePanel.add(rollAddPanel);    // choices
        Utility.fixGrid(cityDatePanel,1);
         add(cityDatePanel);

// BORDER
        // true means raised, false = depressed
        BorderPanel borderPanel = new BorderPanel(true);
        borderPanel.setBackground(Color.lightGray);
        borderPanel.setLayout(null);
        borderPanel.setSize(8,150);
         add(borderPanel);

// LOCALE

        // sets up localePanel
        localePanel=new Panel();
        localePanel.setLayout(new GridLayout(2,1));

        localeLabel=new Label("Locale");
        localeLabel.setFont(Utility.labelFont);
        localeMenu= new Choice();
	localeMenu.addItemListener(this);

        localePanel.add("loc",localeLabel);
        localePanel.add(localeMenu);

        // sets up formatPanel
        formatPanel=new Panel();

        group1= new CheckboxGroup();
        getDateInstance=new Checkbox("Date Format",group1, false);
        getTimeInstance=new Checkbox("Time Format",group1, false);
        getDateTimeInstance=new Checkbox("Date and Time Format",group1, true);

	getDateInstance.addItemListener(this);
	getTimeInstance.addItemListener(this);
	getDateTimeInstance.addItemListener(this);

        Panel formatButtons = new Panel();
        formatButtons.setLayout(new GridLayout(3,1));

        formatButtons.add(getDateInstance);
        formatButtons.add(getTimeInstance);
        formatButtons.add(getDateTimeInstance);

        Panel dateStylePanel=new Panel();
        dateStylePanel.setLayout(new GridLayout(2,1));
        dateStyleLabel=new Label("Date Style");
        dateStyleLabel.setFont(Utility.labelFont);
        dateStyleMenu= new Choice();
	dateStyleMenu.addItemListener(this);
        dateStyleMenu.addItem("Full");
        dateStyleMenu.addItem("Long");
        dateStyleMenu.addItem("Default");
        dateStyleMenu.addItem("Short");
        dateStylePanel.add("loc",dateStyleLabel);
        dateStylePanel.add(dateStyleMenu);

        Panel timeStylePanel=new Panel();
        timeStylePanel.setLayout(new GridLayout(2,1));
        timeStyleLabel=new Label("Time Style");
        timeStyleLabel.setFont(Utility.labelFont);
        timeStyleMenu= new Choice();
	timeStyleMenu.addItemListener(this);
        timeStyleMenu.addItem("Full");
        timeStyleMenu.addItem("Long");
        timeStyleMenu.addItem("Default");
        timeStyleMenu.addItem("Short");
        timeStylePanel.add("loc",timeStyleLabel);
        timeStylePanel.add(timeStyleMenu);

        Panel dtStylePanel = new Panel();
        dtStylePanel.setLayout(new GridLayout(1,2,20,0));
        dtStylePanel.add(dateStylePanel);
        dtStylePanel.add(timeStylePanel);

        formatPanel.add(formatButtons);
        formatPanel.add(dtStylePanel);
        Utility.fixGrid(formatPanel,1);

        Panel localesFormatPanel = new Panel();

        localesFormatPanel.add(localePanel);
        localesFormatPanel.add(formatPanel);
        Utility.fixGrid(localesFormatPanel,1);
         add(localesFormatPanel);

        Panel copyrightPanel = new Panel();
        addWithFont (copyrightPanel,new Label(copyrightString, Label.LEFT),
            Utility.creditFont);
        addWithFont (copyrightPanel,new Label(copyrightString2, Label.LEFT),
            Utility.creditFont);
        Utility.fixGrid(copyrightPanel,1);
         add(copyrightPanel);

        //}}

    }


  /* ActionListener method */
  public void actionPerformed(ActionEvent e) {
    if (e.getSource() == up){
      dateFieldChanged(true);
    } else if (e.getSource() == down) {
      dateFieldChanged(false);
    }
  }

  /* ItemListener method */
  public void itemStateChanged(ItemEvent e) {
    if (e.getSource() == localeMenu) {
      selectedLocaleMenu();
    } else if (e.getSource() == dateStyleMenu) {
      selectedDateStyleMenu();
    } else if (e.getSource() == timeStyleMenu) {
      selectedTimeStyleMenu();
    } else if (e.getSource() == cityMenu) {
      cityChanged();
    } else if (e.getSource() == getRoll) {
      clickedGetRoll();
    } else if (e.getSource() == getAdd) {
      clickedGetAdd();
    } else if (e.getSource() == getLocalized) {
      isLocalized = getLocalized.getState();
      handleNewFormat();
    } else if (e.getSource() == getValidationMode) {
      validationMode = getValidationMode.getState();
      validationModeChanged();      
    } else if (e.getSource() == getDateInstance) {
      clickedGetDateFormat();
    } else if (e.getSource() == getTimeInstance) {
      clickedGetTimeFormat();
    } else if (e.getSource() == getDateTimeInstance) {
      clickedGetDateTimeFormat();
    }
 
  }
  
  /* KeyListener methods */
  public void keyPressed(KeyEvent e) {
  }

  public void keyReleased(KeyEvent e) {
    if (e.getSource() == patternText) {
      e.consume();
      patternTextChanged();
    } else if (e.getSource() == inputText) {
      e.consume();
      formatText();
    } else if (e.getSource() == outputText) {
      e.consume();
      parseText();
    } else if (e.getSource() == millisText) {
      e.consume();
      millisChanged();
    }
  }

  public void keyTyped(KeyEvent e) {
  }
  
  /* Window Listener methods */
  public void windowClosed(WindowEvent e) {
  }

  public void windowDeiconified(WindowEvent e) {
  }

  public void windowIconified(WindowEvent e) {
  }

  public void windowActivated(WindowEvent e) {
  }

  public void windowDeactivated(WindowEvent e) {
  }

  public void windowOpened(WindowEvent e) {
  }

  public void windowClosing(WindowEvent e) {
    setVisible(false);
    dispose();

    if (applet != null) {
      applet.demoClosed();
    } else System.exit(0);

  }


    /**
     * This function is called when users select a new time and/or date
     * format pattern, or a new locale.
     */
    public void setFormatFromLocale(boolean localChanged) {
        int localeIndex = localeMenu.getSelectedIndex();
        int dateStyleIndex = dateStyleMenu.getSelectedIndex()
                             + DateFormat.FULL;
        int timeStyleIndex = timeStyleMenu.getSelectedIndex()
                             + DateFormat.FULL;
        if (localChanged)
            // Find the locale corresponding to the selected menu item
            curLocale = locales[localeIndex];

        if (getDateInstance.getState()) {
            format =
            (SimpleDateFormat) DateFormat.getDateInstance(dateStyleIndex,
                                                        curLocale);
        } else if (getTimeInstance.getState()) {
            format =
            (SimpleDateFormat) DateFormat.getTimeInstance(timeStyleIndex,
                                                        curLocale);
        } else {
            format =
            (SimpleDateFormat) DateFormat.getDateTimeInstance(dateStyleIndex,
                                                            timeStyleIndex,
                                                            curLocale);
        }

        patternText.setText( format.toPattern() );
        if (!localChanged)
        {
            // locale not changed, only pattern format is changed.
            setMillisText();
            millisFormat();
        }
        else // change to selecting a rep. city based on new locale selected
        {
            cityMenu.select(kAdjCityIndex[localeIndex]);
            cityChanged();
        }
    }

    /**
     * This function is called when users change the pattern text.
     */
    public void setFormatFromPattern() {
        String timePattern = patternText.getText();
        format.applyPattern(timePattern);
        millisFormat();
        millisParse();
    }

    private boolean add = false;

    /**
     * This function is called when the "Roll" radio button is selected.
     */
    public  void clickedGetRoll() {
        add=false;
    }

    /**
     * This function is called when the "Add" radio button is selected.
     */
    public void clickedGetAdd() {
        add=true;
    }

    /**
     * This function is called when the "Date Format" radio button is selected.
     */
    public void clickedGetDateFormat() {
        setFormatFromLocale(false);
    }

    /**
     * This function is called when the "Time Format" radio button is selected.
     */
    public void clickedGetTimeFormat() {
        setFormatFromLocale(false);
    }

    /**
     * This function is called when the "Date and Time Format" radio button
     * is selected.
     */
    public void clickedGetDateTimeFormat() {
        setFormatFromLocale(false);
    }

    /**
     * This function is called when a new locale is selected.
     */
    public void selectedLocaleMenu() {
        setFormatFromLocale(true);
    }

    /**
     * This function is called when a new Date (Format) Style is selected.
     */
    public void selectedDateStyleMenu() {
        setFormatFromLocale(false);
    }

    /**
     * This function is called when a new Time (Format) Style is selected.
     */
    public void selectedTimeStyleMenu() {
        setFormatFromLocale(false);
    }

    /**
     * Store the current time in milliseconds.
     */
    long time = System.currentTimeMillis();

    /**
     * This function is called when it is necessary to parse the time
     * string in the "1.0 Date" text field.
     */
    public void formatText() {
        String leftString = inputText.getText();
        if (leftString.length() == 0)
        {
            errorText("Error: no input to format!");
            return;
        }

        try {
	  // intentional use of deprecated method
	  time = Date.parse(leftString); 
        }
        catch (Exception e) {
            outputText.setText("ERROR");
            errorText("Exception: Date.parse: "+leftString);
            return;
        }
        setMillisText();
        millisFormat();
    }

    /**
     * This function is called when it is necessary to parse the time
     * string in the "New Date" text field.
     */
    public void parseText() {
        String rightString = outputText.getText();

        ParsePosition status = new ParsePosition(0);

        if (rightString.length() == 0)
        {
            errorText("Error: no input to parse!");
            return;
        }

        try {
            time = format.parse(rightString, status).getTime();
        }
        catch (Exception e) {
            inputText.setText("ERROR");
            errorText("Exception: parse: "+rightString);
            return;
        }
        setMillisText();
        millisParse();

    }

    /**
     * This function is called when it is necessary to format the time
     * in the "Millis" text field.
     */
    public void millisFormat() {
        String out = "";
        try {
            out = format.format(new Date(time));
        }
        catch (Exception e) {
            outputText.setText("ERROR");
            errorText("Exception: format: "+time);
            return;
        }
        outputText.setText( out );
        errorText("Formatted...");
    }

    /**
     * This function is called when it is necessary to display the time
     * value parsed using GMT string in the "1.0 Date" text field.
     */
    public void millisParse() {
        String input = "";
        try {
	  // intentional use of deprecated method
	  input = new Date(time).toGMTString(); 
            }
        catch (Exception e) {
            inputText.setText("ERROR");
            errorText("Exception: in toGMTString: "+time); 
            return;
        }
        inputText.setText( input );
        errorText("Parsed...");
    }

    /**
     * This function is called when the time value in the "Millis" text field
     * is changed. The new time value will be formatted and displayed in both
     * "New Date" and "1.0 Date" text fields.
     */
    public void millisChanged() {
        String millisString = millisText.getText();
        try {
            time = Long.parseLong(millisString);
            }
        catch (Exception e) {
            errorText("Exception: Bad value for millis. Must be Long");
            return;
        }
        millisFormat();
        millisParse();
        errorText("Millis changed...");
    }

    /**
     * This function is called when it is necessary to display the time
     * value in milliseconds in the "Millis" text field.
     */
    public void setMillisText() {
        millisText.setText(Long.toString(time));
    }

    /**
     * This function is called when users change the pattern text.
     */
    public void patternTextChanged() {
        setFormatFromPattern();
    }

    /**
     * This function is called when users select a new representative city.
     */
    public void cityChanged() {
        int index = cityMenu.getSelectedIndex();

        SimpleTimeZone timeZone = new SimpleTimeZone(kZoneOffsets[index],
                                                     kZoneIDs[index]);
        timeZone.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY,
            2 * millisPerHour);
        timeZone.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY,
            2 * millisPerHour);

        format.setTimeZone(timeZone);

        millisFormat();
        millisParse();
    }

    private boolean addMode() {
        return add;
    }

    /**
     * This function is called when users select a new time field
     * to add or roll its value.
     */
    public void dateFieldChanged(boolean up) {
        String d = dateMenu.getSelectedItem();
        byte field = 0;

        if (d.equals("Year")) {
            field = (byte) Calendar.YEAR;
        } else
        if (d.equals("Month")) {
            field = (byte) Calendar.MONTH;
        } else
        if (d.equals("Day of Month")) {
            field = (byte) Calendar.DATE;
        } else
        if (d.equals("Hour of Day")) {
            field = (byte) Calendar.HOUR_OF_DAY;
        } else
        if (d.equals("Minute")) {
            field = (byte) Calendar.MINUTE;
        } else
        if (d.equals("Second")) {
            field = (byte) Calendar.SECOND;
        } else
        if (d.equals("Millisecond")) {
            field = (byte) Calendar.MILLISECOND;
        }

        format.getCalendar().setTime(new Date(time));
	//        format.getCalendar().computeFields();

        if (up) {
            if (addMode()) {
                format.getCalendar().add(field, 1);
            } else {
                format.getCalendar().roll(field, true);
            }
        } else {
            if (addMode()) {
                format.getCalendar().add(field, -1);
            } else {
                format.getCalendar().roll(field, false);
            }
        }

        time = format.getCalendar().getTime().getTime();

        setMillisText();

        millisFormat();

        millisParse();

    }

    /**
     * Print out the error message while debugging this program.
     */
    public void errorText(String s)
    {
        if (DEBUG)
        {
            System.out.println(s);
        }
    }

}


