001/* ---------------------------------------------------------------------------- 002 The Kiwi Toolkit - A Java Class Library 003 Copyright (C) 1998-2004 Mark A. Lindner 004 005 This library is free software; you can redistribute it and/or 006 modify it under the terms of the GNU General Public License as 007 published by the Free Software Foundation; either version 2 of the 008 License, or (at your option) any later version. 009 010 This library is distributed in the hope that it will be useful, 011 but WITHOUT ANY WARRANTY; without even the implied warranty of 012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 General Public License for more details. 014 015 You should have received a copy of the GNU General Public License 016 along with this library; if not, write to the Free Software 017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 018 02111-1307, USA. 019 020 The author may be contacted at: mark_a_lindner@yahoo.com 021 ---------------------------------------------------------------------------- 022 $Log: DateFormatter.java,v $ 023 Revision 1.5 2004/05/05 22:47:37 markl 024 comment block updates 025 026 Revision 1.4 2003/01/19 09:34:27 markl 027 Javadoc & comment header updates. 028 029 Revision 1.3 2001/03/12 02:18:28 markl 030 Source code cleanup. 031 032 Revision 1.2 1999/01/10 03:37:18 markl 033 added GPL header & RCS tag 034 ---------------------------------------------------------------------------- 035*/ 036 037package kiwi.text; 038 039import java.text.*; 040import java.util.*; 041 042/** This class represents a high-level date parser/formatter that is almost 043 * fully format-string-compatible with the UNIX <b>strftime(3)</b> function. 044 * Date formats are specified by formatting directives; these directives are 045 * enumerated in the table below: 046 * <p> 047 * <center><table border=1 cellspacing=0 cellpadding=2> 048 * <tr><th>Directive</th><th align=left>Meaning</th></tr> 049 * <tr><td>%a</td> <td>Abbreviated weekday name (3 characters).</td></tr> 050 * <tr><td>%A</td> <td>Full weekday name.</td></tr> 051 * <tr><td>%b</td> <td>Abbreviated month name (3 characters).</td></tr> 052 * <tr><td>%B</td> <td>Full month name.</td></tr> 053 * <tr><td>%d</td> <td>Day of month (01-31).</td></tr> 054 * <tr><td>%e</td> <td>Day of month (no leading zero).</td></tr> 055 * <tr><td>%H</td> <td>24-hour clock hour (00-23).</td></tr> 056 * <tr><td>%I</td> <td>12-hour clock hour (01-12).</td></tr> 057 * <tr><td>%j</td> <td>Day in year (001-366).</td></tr> 058 * <tr><td>%m</td> <td>Month in year (01-12).</td></tr> 059 * <tr><td>%M</td> <td>Minutes (00-59).</td></tr> 060 * <tr><td>%N</td> <td>Era name.</td></tr> 061 * <tr><td>%p</td> <td>AM/PM character.</td></tr> 062 * <tr><td>%r</td> <td>Equivalent to %I:%M:%S %p.</td></tr> 063 * <tr><td>%R</td> <td>Equivalent to %H:%M.</td></tr> 064 * <tr><td>%s</td> <td>Milliseconds (000-999).</td></tr> 065 * <tr><td>%S</td> <td>Seconds (00-59).</td></tr> 066 * <tr><td>%t</td> <td>Tab character.</td></tr> 067 * <tr><td>%T</td> <td>Equivalent to %H:%M%:S.</td></tr> 068 * <tr><td>%u</td> <td>Equivalent to %a.</td></tr> 069 * <tr><td>%U</td> <td>Week of year.</td></tr> 070 * <tr><td>%y</td> <td>Year (2 digits).</td></tr> 071 * <tr><td>%Y</td> <td>Year (4 digits).</td></tr> 072 * <tr><td>%Z</td> <td>Time zone name (4 characters).</td></tr> 073 * <tr><td>%%</td> <td>The % character.</td></tr> 074 * <tr><td>. : / - , ;</td> <td>These characters are interpreted literally. 075 * </td></tr> 076 * </table></center> 077 * 078 * @author Mark Lindner 079 */ 080 081public class DateFormatter 082 { 083 private SimpleDateFormat fmt; 084 private String pattern; 085 086 /** Construct a new <code>DateFormatter</code>. See the table of formatting 087 * directives above. 088 * 089 * @param pattern The pattern to be used by this formatter. 090 * @exception java.lang.IllegalArgumentException If the pattern contains 091 * unrecognized formatting directives. 092 */ 093 094 public DateFormatter(String pattern) throws IllegalArgumentException 095 { 096 fmt = new SimpleDateFormat(constructPattern(pattern)); 097 fmt.setTimeZone(TimeZone.getDefault()); 098 } 099 100 /** Parse a date, returning a <code>Date</code> object. 101 * 102 * @param text The text to parse. 103 * @return A <code>Date</code> object corresponding to the parsed date. 104 * @exception ParseException If a parsing error occurred. 105 * @see #format 106 */ 107 108 public Date parse(String text) throws ParseException 109 { 110 return(fmt.parse(text)); 111 } 112 113 /** Format a <code>Calendar</code> object. The date is formatted according 114 * to the pattern specified in this object's constructor. 115 * 116 * @param date The <code>Date</code> to format. 117 * @return The date formatted as a string. 118 * @see #parse 119 */ 120 121 public String format(Calendar date) 122 { 123 return(format(date.getTime())); 124 } 125 126 /** Format the current date. The date is formatted according to the pattern 127 * specified in this object's constructor. 128 * 129 * @return The date formatted as a string. 130 * @see #parse 131 */ 132 133 public String format() 134 { 135 return(format(new Date())); 136 } 137 138 /** Format a date from a <code>Date</code> object. The date is formatted 139 * according to the pattern specified in this object's constructor. 140 * 141 * @param date The <code>Date</code> to format. 142 * @return The date formatted as a string. 143 * @see #parse 144 */ 145 146 public String format(Date date) 147 { 148 return(fmt.format(date)); 149 } 150 151 /* pattern translator */ 152 153 private String constructPattern(String text) throws IllegalArgumentException 154 { 155 StringBuffer sb = new StringBuffer(); 156 boolean escaped = false; 157 158 for(int i = 0; i < text.length(); i++) 159 { 160 char c = text.charAt(i); 161 162 if(!escaped) 163 { 164 switch(c) 165 { 166 case ':': 167 case ';': 168 case '/': 169 case '.': 170 case ',': 171 case '-': 172 case ' ': 173 case '\t': 174 case '(': 175 case ')': 176 sb.append(c); 177 escaped = false; 178 break; 179 180 case '%': 181 if(escaped) 182 { 183 sb.append(c); 184 escaped = false; 185 } 186 else escaped = true; 187 break; 188 189 default: 190 throw(new IllegalArgumentException("Unknown format character :" 191 + c)); 192 } 193 } 194 else 195 { 196 switch(c) 197 { 198 case 'a': 199 sb.append("EE"); 200 break; 201 case 'A': 202 sb.append("EEEE"); 203 break; 204 case 'b': 205 sb.append("MMM"); 206 break; 207 case 'B': 208 sb.append("MMMM"); 209 break; 210 case 'd': 211 sb.append("dd"); 212 break; 213 case 'e': 214 sb.append('d'); 215 break; 216 case 'H': 217 sb.append("HH"); 218 break; 219 case 'I': 220 sb.append("hh"); 221 break; 222 case 'j': 223 sb.append("DDD"); 224 break; 225 case 'm': 226 sb.append("MM"); 227 break; 228 case 'M': 229 sb.append("mm"); 230 break; 231 case 'N': 232 sb.append('G'); 233 break; 234 case 'p': 235 sb.append('a'); 236 break; 237 case 'r': 238 sb.append(constructPattern("%I:%M:%S %p")); 239 break; 240 case 'R': 241 sb.append(constructPattern("%H:%M")); 242 break; 243 case 'S': 244 sb.append("ss"); 245 break; 246 case 't': 247 sb.append('\t'); 248 break; 249 case 'T': 250 sb.append(constructPattern("%H:%M:%S")); 251 break; 252 case 'u': 253 sb.append("EE"); 254 break; 255 case 'U': 256 sb.append("ww"); 257 break; 258 case 's': 259 sb.append("SSS"); 260 break; 261 case 'y': 262 sb.append("yy"); 263 break; 264 case 'Y': 265 sb.append("yyyy"); 266 break; 267 case 'Z': 268 sb.append("zzzz"); 269 break; 270 default: 271 throw(new IllegalArgumentException("Unknown escape sequence: %" 272 + c)); 273 } 274 escaped = false; 275 } 276 } 277 return(sb.toString()); 278 } 279 280 } 281 282/* end of source file */