001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.j2me.global;
028:
029: import java.util.Calendar;
030: import java.util.TimeZone;
031: import javax.microedition.global.Formatter;
032:
033: /**
034: * <code>DateTimeFormat</code> is a concrete class for formatting dates in a
035: * locale-sensitive manner. It allows for formatting (date -> text). <p>
036: *
037: * <code>DateTimeFormat</code> allows you to start by choosing one of
038: * predefined patterns for date-time formatting passing appropriate style to
039: * factory method <code>getInstance(style, locale)</code>.
040: * <table>
041: *
042: * <tr>
043: *
044: * <td>
045: * a
046: * </td>
047: *
048: * <td>
049: * am/pm
050: * </td>
051: *
052: * </tr>
053: *
054: * <tr>
055: *
056: * <td>
057: * H
058: * </td>
059: *
060: * <td>
061: * hour in day 0-23
062: * </td>
063: *
064: * </tr>
065: *
066: * <tr>
067: *
068: * <td>
069: * h
070: * </td>
071: *
072: * <td>
073: * hour in am/pm 0-11
074: * </td>
075: *
076: * </tr>
077: *
078: * <tr>
079: *
080: * <td>
081: * K
082: * </td>
083: *
084: * <td>
085: * hour in day 1-24
086: * </td>
087: *
088: * </tr>
089: *
090: * <tr>
091: *
092: * <td>
093: * k
094: * </td>
095: *
096: * <td>
097: * hour in am/pm 1-12
098: * </td>
099: *
100: * </tr>
101: *
102: * <tr>
103: *
104: * <td>
105: * m
106: * </td>
107: *
108: * <td>
109: * minute 0-59
110: * </td>
111: *
112: * </tr>
113: *
114: * <tr>
115: *
116: * <td>
117: * s
118: * </td>
119: *
120: * <td>
121: * second 0-59
122: * </td>
123: *
124: * </tr>
125: *
126: * <tr>
127: *
128: * <td>
129: * d
130: * </td>
131: *
132: * <td>
133: * day in month (number)
134: * </td>
135: *
136: * </tr>
137: *
138: * <tr>
139: *
140: * <td>
141: * dd
142: * </td>
143: *
144: * <td>
145: * day in month (number 2 digits)
146: * </td>
147: *
148: * </tr>
149: *
150: * <tr>
151: *
152: * <td>
153: * EE
154: * </td>
155: *
156: * <td>
157: * day in week short "Mon"
158: * </td>
159: *
160: * </tr>
161: *
162: * <tr>
163: *
164: * <td>
165: * EEEE
166: * </td>
167: *
168: * <td>
169: * day in week long "Monday"
170: * </td>
171: *
172: * </tr>
173: *
174: * <tr>
175: *
176: * <td>
177: * M
178: * </td>
179: *
180: * <td>
181: * month in year (number)
182: * </td>
183: *
184: * </tr>
185: *
186: * <tr>
187: *
188: * <td>
189: * MM
190: * </td>
191: *
192: * <td>
193: * month in year (number 2 digits)
194: * </td>
195: *
196: * </tr>
197: *
198: * <tr>
199: *
200: * <td>
201: * MMM
202: * </td>
203: *
204: * <td>
205: * month in year short "Oct"
206: * </td>
207: *
208: * </tr>
209: *
210: * <tr>
211: *
212: * <td>
213: * MMMM
214: * </td>
215: *
216: * <td>
217: * month in year long "October"
218: * </td>
219: *
220: * </tr>
221: *
222: * <tr>
223: *
224: * <td>
225: * yy
226: * </td>
227: *
228: * <td>
229: * year short "05"
230: * </td>
231: *
232: * </tr>
233: *
234: * <tr>
235: *
236: * <td>
237: * yyyy
238: * </td>
239: *
240: * <td>
241: * year long "2005"
242: * </td>
243: *
244: * </tr>
245: *
246: * <tr>
247: *
248: * <td>
249: * G
250: * </td>
251: *
252: * <td>
253: * era
254: * </td>
255: *
256: * </tr>
257: *
258: * <tr>
259: *
260: * <td>
261: * z
262: * </td>
263: *
264: * <td>
265: * timezone
266: * </td>
267: *
268: * </tr>
269: *
270: * </table>
271: *
272: *
273: */
274: public class DateTimeFormat {
275:
276: /**
277: * Holds initialized instance of <code>DateFormatSymbols</code> which
278: * encapsulate locale-dependent information like names of days in week,
279: * months etc.
280: */
281: private DateFormatSymbols symbols;
282:
283: /**
284: * Style of date/time formatting.
285: *
286: * @see Formatter#TIME_LONG
287: * @see Formatter#TIME_SHORT
288: * @see Formatter#DATE_LONG
289: * @see Formatter#DATE_SHORT
290: * @see Formatter#DATETIME_LONG
291: * @see Formatter#DATETIME_SHORT
292: */
293: private int style;
294:
295: /**
296: * Creates new <code>DateTimeFormat</code> object. It is assumed that
297: * <code>style</code> contains correct value and <code>symbols</code>
298: * refers to properly initialized <code>DateFormatSymbols</code> object.
299: *
300: * @param style predefined date/time style
301: * @param symbols object encapsulating localized DateTime symbols
302: */
303: public DateTimeFormat(int style, DateFormatSymbols symbols) {
304: this .style = style;
305: this .symbols = symbols;
306: }
307:
308: /**
309: * Formats date/time with the current <code>style</code>.
310: *
311: * @param calendar date/time to format
312: * @param nf integer instance of <code>NumberFormat</code> to
313: * perform formatting of integer date and time values
314: * @return formatted string
315: */
316: protected String format(Calendar calendar, NumberFormat nf) {
317: StringBuffer appendTo = new StringBuffer();
318: StringBuffer pattern = new StringBuffer(symbols.patterns[style]);
319: nf.setGroupingUsed(false);
320: char c;
321: int value;
322: int digits;
323:
324: if (style == Formatter.DATETIME_SHORT) {
325: // date first paremeter, time second
326: pattern = new StringBuffer(MessageFormat.format(
327: symbols.patterns[style], new String[] {
328: symbols.patterns[Formatter.DATE_SHORT],
329: symbols.patterns[Formatter.TIME_SHORT] }));
330:
331: } else if (style == Formatter.DATETIME_LONG) {
332: pattern = new StringBuffer(MessageFormat.format(
333: symbols.patterns[style], new String[] {
334: symbols.patterns[Formatter.DATE_LONG],
335: symbols.patterns[Formatter.TIME_LONG] }));
336: }
337: for (int i = 0; i < pattern.length(); i++) {
338: c = pattern.charAt(i);
339: switch (c) {
340: case 'a':
341: // AM or PM symbol
342: int ampm = calendar.get(Calendar.AM_PM);
343: appendTo.append(symbols.ampms[ampm == Calendar.AM ? 0
344: : 1]);
345: break;
346: case 'H':
347: // Hours in 24-hour mode 0 - based
348: value = calendar.get(Calendar.HOUR_OF_DAY);
349: digits = ((i + 1) < pattern.length() && pattern
350: .charAt(i + 1) == 'H') ? 2 : 1;
351: nf.setMinimumIntegerDigits(digits);
352: appendTo.append(nf.format(value));
353: i += digits - 1;
354: break;
355: case 'h':
356: // Hours in 12-hour mode, 1 - based
357: value = calendar.get(Calendar.HOUR);
358: digits = ((i + 1) < pattern.length() && pattern
359: .charAt(i + 1) == 'h') ? 2 : 1;
360: nf.setMinimumIntegerDigits(digits);
361: appendTo.append(nf.format(value));
362: i += digits - 1;
363: break;
364: case 'K':
365: // Hours in 12-hour mode 0 - based
366: value = calendar.get(Calendar.HOUR_OF_DAY);
367: value = value > 12 ? value % 12 : value; // noon is 12 midnight is 0
368: digits = ((i + 1) < pattern.length() && pattern
369: .charAt(i + 1) == 'K') ? 2 : 1;
370: nf.setMinimumIntegerDigits(digits);
371: appendTo.append(nf.format(value));
372: i += digits - 1;
373: break;
374: case 'k':
375: // Hours in 24-hour mode 1 based
376: value = calendar.get(Calendar.HOUR_OF_DAY);
377: value = (value == 0) ? 24 : value;
378: digits = ((i + 1) < pattern.length() && pattern
379: .charAt(i + 1) == 'k') ? 2 : 1;
380: nf.setMinimumIntegerDigits(digits);
381: appendTo.append(nf.format(value));
382: i += digits - 1;
383: break;
384: case 'm':
385: // Minutes
386: value = calendar.get(Calendar.MINUTE);
387: digits = ((i + 1) < pattern.length() && pattern
388: .charAt(i + 1) == 'm') ? 2 : 1;
389: nf.setMinimumIntegerDigits(digits);
390: appendTo.append(nf.format(value));
391: i += digits - 1;
392: break;
393: case 's':
394: // Seconds
395: value = calendar.get(Calendar.SECOND);
396: digits = ((i + 1) < pattern.length() && pattern
397: .charAt(i + 1) == 's') ? 2 : 1;
398: nf.setMinimumIntegerDigits(digits);
399: appendTo.append(nf.format(value));
400: i += digits - 1;
401: break;
402: case 'E':
403: // Long or short weekday name
404: if ((i + 3) < pattern.length()
405: && pattern.charAt(i + 1) == 'E'
406: && pattern.charAt(i + 2) == 'E'
407: && pattern.charAt(i + 3) == 'E') {
408: // long day of week name
409: value = calendar.get(Calendar.DAY_OF_WEEK);
410: appendTo.append(symbols.weekDays[value]);
411: i += 3;
412: } else if ((i + 1) < pattern.length()
413: && pattern.charAt(i + 1) == 'E') {
414: // short day of week name
415: value = calendar.get(Calendar.DAY_OF_WEEK);
416: appendTo.append(symbols.shortWeekDays[value]);
417: i += 1;
418: }
419: break;
420: case 'd':
421: // Numeric day of month
422: if ((i + 1) < pattern.length()
423: && pattern.charAt(i + 1) == 'd') {
424: // numeric day 2 digits
425: value = calendar.get(Calendar.DAY_OF_MONTH);
426: nf.setMinimumIntegerDigits(2);
427: appendTo.append(nf.format(value));
428: i += 1;
429: } else {
430: // numeric day 1 digit
431: value = calendar.get(Calendar.DAY_OF_MONTH);
432: nf.setMinimumIntegerDigits(1);
433: appendTo.append(nf.format(value));
434: }
435: break;
436: case 'M':
437: // Long or short month name or numeric month
438: if ((i + 3) < pattern.length()
439: && pattern.charAt(i + 1) == 'M'
440: && pattern.charAt(i + 2) == 'M'
441: && pattern.charAt(i + 3) == 'M') {
442: // long month name
443: value = calendar.get(Calendar.MONTH);
444: appendTo.append(symbols.months[value]);
445: i += 3;
446: } else if ((i + 2) < pattern.length()
447: && pattern.charAt(i + 1) == 'M'
448: && pattern.charAt(i + 2) == 'M') {
449: // short month name
450: value = calendar.get(Calendar.MONTH);
451: appendTo.append(symbols.shortMonths[value]);
452: i += 2;
453: } else if ((i + 1) < pattern.length()
454: && pattern.charAt(i + 1) == 'M') {
455: value = calendar.get(Calendar.MONTH) + 1;
456: nf.setMinimumIntegerDigits(2);
457: appendTo.append(nf.format(value));
458: i += 1;
459: } else {
460: value = calendar.get(Calendar.MONTH) + 1;
461: nf.setMinimumIntegerDigits(1);
462: appendTo.append(nf.format(value));
463: }
464: break;
465: case 'y':
466: // Long or short year
467: value = calendar.get(Calendar.YEAR);
468: if ((i + 3) < pattern.length()
469: && pattern.charAt(i + 1) == 'y'
470: && pattern.charAt(i + 2) == 'y'
471: && pattern.charAt(i + 3) == 'y') {
472: // long year
473: nf.setMinimumIntegerDigits(4);
474: appendTo.append(nf.format(value));
475: i += 3;
476: } else if ((i + 1) < pattern.length()
477: && pattern.charAt(i + 1) == 'y') {
478: // short year
479: nf.setMinimumIntegerDigits(2);
480: String y = nf.format(value);
481: appendTo.append(y.substring(y.length() - 2, y
482: .length()));
483: i += 1;
484: }
485: break;
486: /*
487: * case 'G': // not in midp
488: * value = calendar.get(Calendar.ERA);
489: * appendTo.append(symbols.eras[value]);
490: * break;
491: */
492: case 'z':
493: // Time zone
494: TimeZone tzone = calendar.getTimeZone();
495: if (tzone == null) {
496: break;
497: }
498: int offset = tzone.getRawOffset();
499: if (offset == 0) {
500: appendTo.append('Z');
501: } else {
502: offset /= 3600000;
503: if (offset >= 0) {
504: appendTo.append('+');
505: } else {
506: appendTo.append('-');
507: offset = -offset;
508: }
509: if (offset < 10) {
510: appendTo.append('0');
511: }
512: appendTo.append(offset);
513: appendTo.append(":00");
514: }
515: break;
516: default:
517: appendTo.append(c);
518:
519: }
520: }
521: // for
522: return appendTo.toString();
523: }
524: }
|