FileDocCategorySizeDatePackage
DateTimeFormat.javaAPI DocphoneME MR2 API (J2ME)14989Wed May 02 18:00:46 BST 2007com.sun.j2me.global

DateTimeFormat.java

/*
 *   
 *
 * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 only, as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License version 2 for more details (a copy is
 * included at /legal/license.txt).
 * 
 * You should have received a copy of the GNU General Public License
 * version 2 along with this work; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * 
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 * Clara, CA 95054 or visit www.sun.com if you need additional
 * information or have any questions.
 */

package com.sun.j2me.global;

import java.util.Calendar;
import java.util.TimeZone;
import javax.microedition.global.Formatter;

/**
 *  <code>DateTimeFormat</code> is a concrete class for formatting dates in a
 *  locale-sensitive manner. It allows for formatting (date -> text). <p>
 *
 *  <code>DateTimeFormat</code> allows you to start by choosing one of
 *  predefined patterns for date-time formatting passing appropriate style to
 *  factory method <code>getInstance(style, locale)</code>.
 *  <table>
 *
 *    <tr>
 *
 *      <td>
 *        a
 *      </td>
 *
 *      <td>
 *        am/pm
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        H
 *      </td>
 *
 *      <td>
 *        hour in day 0-23
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        h
 *      </td>
 *
 *      <td>
 *        hour in am/pm 0-11
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        K
 *      </td>
 *
 *      <td>
 *        hour in day 1-24
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        k
 *      </td>
 *
 *      <td>
 *        hour in am/pm 1-12
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        m
 *      </td>
 *
 *      <td>
 *        minute 0-59
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        s
 *      </td>
 *
 *      <td>
 *        second 0-59
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        d
 *      </td>
 *
 *      <td>
 *        day in month (number)
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        dd
 *      </td>
 *
 *      <td>
 *        day in month (number 2 digits)
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        EE
 *      </td>
 *
 *      <td>
 *        day in week short "Mon"
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        EEEE
 *      </td>
 *
 *      <td>
 *        day in week long "Monday"
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        M
 *      </td>
 *
 *      <td>
 *        month in year (number)
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        MM
 *      </td>
 *
 *      <td>
 *        month in year (number 2 digits)
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        MMM
 *      </td>
 *
 *      <td>
 *        month in year short "Oct"
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        MMMM
 *      </td>
 *
 *      <td>
 *        month in year long "October"
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        yy
 *      </td>
 *
 *      <td>
 *        year short "05"
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        yyyy
 *      </td>
 *
 *      <td>
 *        year long "2005"
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        G
 *      </td>
 *
 *      <td>
 *        era
 *      </td>
 *
 *    </tr>
 *
 *    <tr>
 *
 *      <td>
 *        z
 *      </td>
 *
 *      <td>
 *        timezone
 *      </td>
 *
 *    </tr>
 *
 *  </table>
 *
 *
 */
public class DateTimeFormat {

    /**
     * Holds initialized instance of <code>DateFormatSymbols</code> which
     * encapsulate locale-dependent information like names of days in week,
     * months etc.
     */
    private DateFormatSymbols symbols;

    /**
     * Style of date/time formatting.
     *
     * @see    Formatter#TIME_LONG
     * @see    Formatter#TIME_SHORT
     * @see    Formatter#DATE_LONG
     * @see    Formatter#DATE_SHORT
     * @see    Formatter#DATETIME_LONG
     * @see    Formatter#DATETIME_SHORT
     */
    private int style;

    /**
     * Creates new <code>DateTimeFormat</code> object. It is assumed that
     * <code>style</code> contains correct value and <code>symbols</code>
     * refers to properly initialized <code>DateFormatSymbols</code> object.
     *
     * @param  style    predefined date/time style
     * @param  symbols  object encapsulating localized DateTime symbols
     */
    public DateTimeFormat(int style, DateFormatSymbols symbols) {
        this.style = style;
        this.symbols = symbols;
    }


    /**
     * Formats date/time with the current <code>style</code>.
     *
     * @param  calendar  date/time to format
     * @param  nf        integer instance of <code>NumberFormat</code> to
     *                   perform formatting of integer date and time values
     * @return           formatted string
     */
    protected String format(Calendar calendar, NumberFormat nf) {
        StringBuffer appendTo = new StringBuffer();
        StringBuffer pattern = new StringBuffer(symbols.patterns[style]);
        nf.setGroupingUsed(false);
        char c;
        int value;
        int digits;

        if (style == Formatter.DATETIME_SHORT) {
            //  date first paremeter, time second
            pattern = new StringBuffer(MessageFormat.format(
                    symbols.patterns[style],
                    new String[] {symbols.patterns[Formatter.DATE_SHORT],
                    symbols.patterns[Formatter.TIME_SHORT]}));

        } else if (style == Formatter.DATETIME_LONG) {
            pattern = new StringBuffer(MessageFormat.format(
                    symbols.patterns[style],
                    new String[] {symbols.patterns[Formatter.DATE_LONG],
                    symbols.patterns[Formatter.TIME_LONG]}));
        }
        for (int i = 0; i < pattern.length(); i++) {
            c = pattern.charAt(i);
            switch (c) {
                case 'a':
                    // AM or PM symbol
                    int ampm = calendar.get(Calendar.AM_PM);
                    appendTo.append(symbols.ampms[ampm == Calendar.AM ? 0 : 1]);
                    break;
                case 'H':
                    // Hours in 24-hour mode 0 - based
                    value = calendar.get(Calendar.HOUR_OF_DAY);
                    digits = ((i + 1) < pattern.length() &&
                            pattern.charAt(i + 1) == 'H') ? 2 : 1;
                    nf.setMinimumIntegerDigits(digits);
                    appendTo.append(nf.format(value));
                    i += digits - 1;
                    break;
                case 'h':
                    // Hours in 12-hour mode, 1 - based
                    value = calendar.get(Calendar.HOUR);
                    digits = ((i + 1) < pattern.length() &&
                            pattern.charAt(i + 1) == 'h') ? 2 : 1;
                    nf.setMinimumIntegerDigits(digits);
                    appendTo.append(nf.format(value));
                    i += digits - 1;
                    break;
                case 'K':
                    // Hours in 12-hour mode 0 - based
                    value = calendar.get(Calendar.HOUR_OF_DAY);
                    value = value>12 ? value % 12 : value;  // noon is 12 midnight is 0
                    digits = ((i + 1) < pattern.length() &&
                            pattern.charAt(i + 1) == 'K') ? 2 : 1;
                    nf.setMinimumIntegerDigits(digits);
                    appendTo.append(nf.format(value));
                    i += digits - 1;
                    break;
                case 'k':
                    // Hours in 24-hour mode 1 based
                    value = calendar.get(Calendar.HOUR_OF_DAY);
                    value = (value == 0) ? 24 : value;
                    digits = ((i + 1) < pattern.length() &&
                            pattern.charAt(i + 1) == 'k') ? 2 : 1;
                    nf.setMinimumIntegerDigits(digits);
                    appendTo.append(nf.format(value));
                    i += digits - 1;
                    break;
                case 'm':
                    // Minutes
                    value = calendar.get(Calendar.MINUTE);
                    digits = ((i + 1) < pattern.length() &&
                            pattern.charAt(i + 1) == 'm') ? 2 : 1;
                    nf.setMinimumIntegerDigits(digits);
                    appendTo.append(nf.format(value));
                    i += digits - 1;
                    break;
                case 's':
                    // Seconds
                    value = calendar.get(Calendar.SECOND);
                    digits = ((i + 1) < pattern.length() &&
                            pattern.charAt(i + 1) == 's') ? 2 : 1;
                    nf.setMinimumIntegerDigits(digits);
                    appendTo.append(nf.format(value));
                    i += digits - 1;
                    break;
                case 'E':
                    // Long or short weekday name
                    if ((i + 3) < pattern.length() &&
                            pattern.charAt(i + 1) == 'E' &&
                            pattern.charAt(i + 2) == 'E' &&
                            pattern.charAt(i + 3) == 'E') {
                        // long day of week name
                        value = calendar.get(Calendar.DAY_OF_WEEK);
                        appendTo.append(symbols.weekDays[value]);
                        i += 3;
                    } else if ((i + 1) < pattern.length() &&
                            pattern.charAt(i + 1) == 'E') {
                        // short day of week name
                        value = calendar.get(Calendar.DAY_OF_WEEK);
                        appendTo.append(symbols.shortWeekDays[value]);
                        i += 1;
                    }
                    break;
                case 'd':
                    // Numeric day of month
                    if ((i + 1) < pattern.length() &&
                            pattern.charAt(i + 1) == 'd') {
                        // numeric day 2 digits
                        value = calendar.get(Calendar.DAY_OF_MONTH);
                        nf.setMinimumIntegerDigits(2);
                        appendTo.append(nf.format(value));
                        i += 1;
                    } else {
                        // numeric day 1 digit
                        value = calendar.get(Calendar.DAY_OF_MONTH);
                        nf.setMinimumIntegerDigits(1);
                        appendTo.append(nf.format(value));
                    }
                    break;
                case 'M':
                    // Long or short month name or numeric month
                    if ((i + 3) < pattern.length() &&
                            pattern.charAt(i + 1) == 'M' &&
                            pattern.charAt(i + 2) == 'M' &&
                            pattern.charAt(i + 3) == 'M') {
                        // long month name
                        value = calendar.get(Calendar.MONTH);
                        appendTo.append(symbols.months[value]);
                        i += 3;
                    } else if ((i + 2) < pattern.length() &&
                            pattern.charAt(i + 1) == 'M' &&
                            pattern.charAt(i + 2) == 'M') {
                        // short month name
                        value = calendar.get(Calendar.MONTH);
                        appendTo.append(symbols.shortMonths[value]);
                        i += 2;
                    } else if ((i + 1) < pattern.length() &&
                            pattern.charAt(i + 1) == 'M') {
                        value = calendar.get(Calendar.MONTH) + 1;
                        nf.setMinimumIntegerDigits(2);
                        appendTo.append(nf.format(value));
                        i += 1;
                    } else {
                        value = calendar.get(Calendar.MONTH) + 1;
                        nf.setMinimumIntegerDigits(1);
                        appendTo.append(nf.format(value));
                    }
                    break;
                case 'y':
                    // Long or short year
                    value = calendar.get(Calendar.YEAR);
                    if ((i + 3) < pattern.length() &&
                            pattern.charAt(i + 1) == 'y' &&
                            pattern.charAt(i + 2) == 'y' &&
                            pattern.charAt(i + 3) == 'y') {
                        // long year
                        nf.setMinimumIntegerDigits(4);
                        appendTo.append(nf.format(value));
                        i += 3;
                    } else if ((i + 1) < pattern.length() &&
                            pattern.charAt(i + 1) == 'y') {
                        // short year
                        nf.setMinimumIntegerDigits(2);
                        String y = nf.format(value);
                        appendTo.append(y.substring(y.length() - 2,
                                y.length()));
                        i += 1;
                    }
                    break;
                /*
                 *  case 'G': // not in midp
                 *  value = calendar.get(Calendar.ERA);
                 *  appendTo.append(symbols.eras[value]);
                 *  break;
                 */
                case 'z':
                    // Time zone
                    TimeZone tzone = calendar.getTimeZone();
                    if (tzone == null) {
                        break;
                    }
                    int offset = tzone.getRawOffset();
                    if (offset == 0) {
                        appendTo.append('Z');
                    } else {
                        offset /= 3600000;
                        if (offset >= 0) {
                            appendTo.append('+');
                        } else {
                            appendTo.append('-');
                            offset = -offset;
                        }
                        if (offset < 10) {
                            appendTo.append('0');
                        }
                        appendTo.append(offset);
                        appendTo.append(":00");
                    }
                    break;
                default:
                    appendTo.append(c);

            }
        }
        // for
        return appendTo.toString();
    }
}