001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: package com.jcorporate.expresso.core.misc;
066:
067: import com.jcorporate.expresso.core.db.DBException;
068: import com.jcorporate.expresso.core.i18n.Messages;
069: import com.jcorporate.expresso.kernel.util.FastStringBuffer;
070: import org.apache.log4j.Logger;
071:
072: import java.lang.ref.SoftReference;
073: import java.text.DateFormat;
074: import java.text.SimpleDateFormat;
075: import java.util.Calendar;
076: import java.util.Date;
077: import java.util.GregorianCalendar;
078: import java.util.HashMap;
079: import java.util.Locale;
080: import java.util.Map;
081:
082: /**
083: * prepare timestamps for database storage
084: *
085: * @author Michael Nash
086: * @author Michael Rimov
087: * @author Yves Henri Amaizo
088: * @author David Lloyd
089: */
090: public class DateTime {
091:
092: private static final Logger log = Logger.getLogger(DateTime.class);
093:
094: /**
095: * Constructor
096: */
097: public DateTime() {
098: super ();
099: } /* DateTime() */
100:
101: /**
102: * Return the current date as a formatted string
103: *
104: * @return String The current date
105: */
106: public static String getDateString() {
107: Calendar rightNow = Calendar.getInstance();
108:
109: return ("" + (rightNow.get(Calendar.MONTH) + 1) + "/"
110: + rightNow.get(Calendar.DAY_OF_MONTH) + "/" + rightNow
111: .get(Calendar.YEAR)).trim();
112: } /* getDateString() */
113:
114: /**
115: * Get a date/time field formatted for insertion into a database
116: * Value of the date/time is the current date and time
117: *
118: * @return String The formatted date time field
119: */
120: public static String getDateTimeForDB()
121: throws com.jcorporate.expresso.core.db.DBException {
122: return getDateTimeForDB(new Date(), "default");
123: } /* getDateTimeForDB() */
124:
125: /**
126: * Get a date/time field formatted for insertion into a database
127: * Value of the date/time is the current date and time
128: *
129: * @param dbContext the database context to which to format this for.
130: * @return String The formatted date time field
131: */
132: public static String getDateTimeForDB(String dbContext)
133: throws DBException {
134: return getDateTimeForDB(new Date(), dbContext);
135: }
136:
137: /**
138: * Get a date/time field formatted for insertion into a database
139: * Value of the date/time is the current date and time
140: *
141: * @param year integer year
142: * @param month integer month value
143: * @param day integer day value
144: * @param hour integer hour value
145: * @param min integer minutes value
146: * @param sec integer seconds value
147: * @param context the data context to format this date-time string for.
148: * @return String The formatted date time field
149: */
150: public static String getDateTimeForDB(int year, int month, int day,
151: int hour, int min, int sec, String context)
152: throws com.jcorporate.expresso.core.db.DBException {
153: Calendar cal = new GregorianCalendar(year, month, day, hour,
154: min, sec);
155:
156: return getDateTimeForDB(cal.getTime(), context);
157: } /* getDateTimeForDB(int, int, int, int, int, int) */
158:
159: /**
160: * Get a date/time field formatted for insertion into a database
161: *
162: * @param date java.util.Date to format into a string for a database
163: * @param context the data context to format the string for.
164: * @return String The formatted date time field
165: */
166: public static String getDateTimeForDB(Date date, String context)
167: throws com.jcorporate.expresso.core.db.DBException {
168: if (date == null) {
169: return null;
170: }
171:
172: String convertFormat = null;
173:
174: // Format the current time. SimpleDateFormat formatter
175: try {
176: ConfigJdbc myConfig = ConfigManager
177: .getJdbcRequired(context);
178:
179: convertFormat = StringUtil.notNull(myConfig
180: .getDateTimeSelectFormat());
181: } catch (ConfigurationException ce) {
182: throw new com.jcorporate.expresso.core.db.DBException(ce);
183: }
184:
185: /* If no format was specified, don't change the existing field */
186: SimpleDateFormat formatter = null;
187: if (convertFormat.equals("")) {
188: // Format the current time. SimpleDateFormat formatter
189: formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
190: } else {
191: formatter = new SimpleDateFormat(convertFormat);
192: }
193:
194: return formatter.format(date).trim();
195:
196: } /* getDateTimeForDB(Date) */
197:
198: /**
199: * Get a date/time field formatted for insertion into a database
200: * Value of the date/time is the current date and time
201: *
202: * @param year integer year
203: * @param month integer month value
204: * @param day integer day value
205: * @param hour integer hour value
206: * @param min integer minutes value
207: * @param sec integer seconds value
208: * @return String The formatted date time field
209: * @throws DBException upon error
210: */
211: public static String getDateTimeForDB(int year, int month, int day,
212: int hour, int min, int sec)
213: throws com.jcorporate.expresso.core.db.DBException {
214: Calendar cal = new GregorianCalendar(year, month, day, hour,
215: min, sec);
216:
217: return getDateTimeForDB(cal.getTime()).trim();
218: } /* getDateTimeForDB(int, int, int, int, int, int) */
219:
220: /**
221: * Get a date/time field formatted for insertion into a database (default
222: * context)
223: *
224: * @param date the <code>java.util.Date</code> object to format for the
225: * database.
226: * @return String The formatted date time field
227: */
228: public static String getDateTimeForDB(Date date)
229: throws com.jcorporate.expresso.core.db.DBException {
230: return getDateTimeForDB(date, "default");
231: } /* getDateTimeForDB(Date) */
232:
233: /**
234: * Get a date/time string containing the current date and time,
235: * formatted for user readability
236: *
237: * @return String The formatted current date/time
238: */
239: public static String getDateTimeString() {
240:
241: /* Calendar rightNow = Calendar.getInstance();
242: return ("" + (rightNow.get(Calendar.MONTH) + 1)+ "/"
243: + rightNow.get(Calendar.DAY_OF_MONTH)
244: + "/" + rightNow.get(Calendar.YEAR) + " "
245: + rightNow.get(Calendar.HOUR)
246: + ":" + rightNow.get(Calendar.MINUTE)
247: + ":" + rightNow.get(Calendar.SECOND)).trim(); */
248:
249: // Format the current time. SimpleDateFormat formatter
250: SimpleDateFormat formatter = new SimpleDateFormat(
251: "E',' MMM d yyyy 'at' hh:mm:ss a");
252: Date currentTime_1 = new Date();
253: String dateString = formatter.format(currentTime_1);
254:
255: return dateString.trim();
256: } /* getDateTimeString() */
257:
258: /**
259: * Get a date/time string for a given date and time,
260: * formatted for user readability
261: *
262: * @param date <code>java.util.Date</code> to format for the default database
263: * @return String The formatted current date/time
264: */
265: public static String getDateTimeString(Date date) {
266: if (date == null) {
267: return null;
268: }
269: // Format the current time. SimpleDateFormat formatter
270: SimpleDateFormat formatter = new SimpleDateFormat(
271: "E',' MMM d yyyy 'at' hh:mm:ss a");
272: String dateString = formatter.format(date);
273:
274: return dateString.trim();
275: } /* getDateTimeString() */
276:
277: /**
278: * Get a time field formatted for insertion into a database
279: * Value of the time is the current time
280: *
281: * @return String The formatted time field
282: * @throws DBException upon error
283: */
284: public static String getTimeForDB()
285: throws com.jcorporate.expresso.core.db.DBException {
286: return getTimeForDB(new Date(), "default");
287: } /* getTimeForDB() */
288:
289: /**
290: * Get atime field formatted for insertion into a database
291: *
292: * @param hour hours as an int
293: * @param min minutes as an int
294: * @param sec seconds as an int
295: * @return String The formatted time field
296: */
297: public static String getTimeForDB(int hour, int min, int sec)
298: throws com.jcorporate.expresso.core.db.DBException {
299: Calendar cal = new GregorianCalendar();
300: cal.set(Calendar.HOUR_OF_DAY, hour);
301: cal.set(Calendar.MINUTE, min);
302: cal.set(Calendar.SECOND, sec);
303:
304: return getTimeForDB(cal.getTime(), "default");
305: } /* getTimeForDB(int, int, int) */
306:
307: /**
308: * Get a time field formatted for insertion into a database
309: *
310: * @param date the <code>java.util.Date</code> object to format for
311: * the default database
312: * @return String The formatted time field
313: */
314: public static String getTimeForDB(Date date)
315: throws com.jcorporate.expresso.core.db.DBException {
316: return getTimeForDB(date, "default");
317: } /* getTimeForDB(Date) */
318:
319: /**
320: * Takes into account for the database context.
321: *
322: * @param date the <code>java.util.Date</code> object to format for
323: * @param context the data context to get the formatted string for.
324: * @return java.lang.String formatted for the specified context
325: */
326: public static String getTimeForDB(Date date, String context)
327: throws com.jcorporate.expresso.core.db.DBException {
328: if (date == null) {
329: return null;
330: }
331:
332: StringUtil
333: .assertNotBlank(context,
334: "DateTime.getTimeForDB(): parameter 'context' may not be mull");
335:
336: String convertFormat = null;
337:
338: // Format the current time. SimpleDateFormat formatter
339: try {
340: ConfigJdbc myConfig = ConfigManager
341: .getJdbcRequired(context);
342:
343: convertFormat = StringUtil.notNull(myConfig
344: .getTimeSelectFormat());
345: } catch (ConfigurationException ce) {
346: throw new com.jcorporate.expresso.core.db.DBException(ce);
347: }
348:
349: /* If no format was specified, don't change the existing field */
350: SimpleDateFormat formatter = null;
351: if (convertFormat.equals("")) {
352: // Format the current time. SimpleDateFormat formatter
353: formatter = new SimpleDateFormat("HH:mm:ss");
354: } else {
355: formatter = new SimpleDateFormat(convertFormat);
356: }
357:
358: return formatter.format(date).trim();
359: }
360:
361: /**
362: * Get a date field formatted for insertion into a database
363: * Value of the date is the current date
364: * author Yves Henri AMAIZO
365: *
366: * @return String The formatted date field
367: */
368: public static String getDateForDB()
369: throws com.jcorporate.expresso.core.db.DBException {
370: return getDateForDB(new Date(), "default");
371: } /* getTimeForDB() */
372:
373: /**
374: * Get a date field formatted for insertion into a database
375: * author Yves Henri AMAIZO
376: *
377: * @param year The year as an integer. ex: 1999
378: * @param mon The month as an integer [0-11]
379: * @param day of month The day of the month [1-31 variable]
380: * @return String The formatted date field
381: */
382: public static String getDateForDB(int year, int mon, int day)
383: throws com.jcorporate.expresso.core.db.DBException {
384: Calendar cal = new GregorianCalendar();
385: cal.set(Calendar.YEAR, year);
386: cal.set(Calendar.MONTH, mon);
387: cal.set(Calendar.DAY_OF_MONTH, day);
388:
389: return getDateForDB(cal.getTime(), "default");
390: } /* getTimeForDB(int, int, int) */
391:
392: /**
393: * Get a time field formatted for insertion into a database
394: * author Yves Henri AMAIZO
395: *
396: * @param date The java.util.Date to format
397: * @return String The formatted date field
398: */
399: public static String getDateForDB(Date date)
400: throws com.jcorporate.expresso.core.db.DBException {
401: return getDateForDB(date, "default");
402: } /* getTimeForDB(Date) */
403:
404: /**
405: * Takes into account for the database context.
406: * author Yves Henri AMAIZO
407: *
408: * @param date The java.util.Date to format
409: * @param context The data context to format for
410: * @return String formatted for the specified database
411: */
412: public static String getDateForDB(Date date, String context)
413: throws DBException {
414:
415: if (date == null) {
416: return null;
417: }
418:
419: StringUtil
420: .assertNotBlank(context,
421: "DateTime.getDateForDB(): parameter context may not be mull");
422:
423: String convertFormat = null;
424:
425: // Format the current time. SimpleDateFormat formatter
426: try {
427: ConfigJdbc myConfig = ConfigManager
428: .getJdbcRequired(context);
429:
430: convertFormat = StringUtil.notNull(myConfig
431: .getDateSelectFormat());
432: } catch (ConfigurationException ce) {
433: throw new com.jcorporate.expresso.core.db.DBException(ce);
434: }
435:
436: /* If no format was specified, don't change the existing field */
437: SimpleDateFormat formatter = null;
438: if (convertFormat.equals("")) {
439: // Format the current time. SimpleDateFormat formatter
440: formatter = new SimpleDateFormat("yyyy-MM-dd");
441: } else {
442: formatter = new SimpleDateFormat(convertFormat);
443: }
444:
445: return formatter.format(date).trim();
446: }
447:
448: /**
449: * map of locale to date format strings for getDateFormatStrings()
450: */
451: transient private static SoftReference sDateFormatStrings = new SoftReference(
452: new HashMap());
453:
454: /**
455: * Get the Date or DateTime format for a Locale. For each of the date format characters (M,d,y,h,H,k,K,m,s),
456: * a lookup is made in the message bundle for the data format wanted.
457: * <br>
458: * For example, if DateFormat.getDateInstance(DateFormat.SHORT,locale) returns "M/dd/yy" and you wanted to show
459: * "mm/dd/yyyy" to the user, the resource bundle com.jcorporate.expresso.core.MessageBundle would need
460: * <br><pre>
461: * datetime.format.MM = mm
462: * datetime.format.dd = dd
463: * datetime.format.yy = yyyy
464: * </pre><br>
465: * <p/>
466: * The entries are cached because the DateFormat calls are VERY expensive.
467: * author David Lloyd
468: *
469: * @param dateOnly True if this is to get a date only format (m/d/yy) versus DateTime (m/d/yy h:m:s)
470: * @param locale The locale to get the format for. This may not be null
471: * @return String formatted for the date
472: */
473: public static String getDateFormatString(boolean dateOnly,
474: Locale locale) {
475: DateTime.DateFormatCacheItem item = null;
476: String pattern = "";
477: String datePattern = "";
478: String dateTimePattern = "";
479:
480: synchronized (sDateFormatStrings) {
481: Map dateFormatStrings = (Map) sDateFormatStrings.get();
482: if (dateFormatStrings == null) {
483: dateFormatStrings = new HashMap();
484: sDateFormatStrings = new SoftReference(
485: dateFormatStrings);
486: }
487:
488: item = (DateTime.DateFormatCacheItem) dateFormatStrings
489: .get(DateFormatCacheItem.deriveKey(locale));
490:
491: if (item == null) {
492: DateFormat dateFormat;
493: DateFormat dateTimeFormat;
494: dateFormat = DateFormat.getDateInstance(
495: DateFormat.SHORT, locale);
496: dateTimeFormat = DateFormat.getDateTimeInstance(
497: DateFormat.SHORT, DateFormat.SHORT, locale);
498:
499: if (dateFormat instanceof SimpleDateFormat) {
500: SimpleDateFormat simpleDateFormat = (SimpleDateFormat) dateFormat;
501: datePattern = convertDateFormatStringToLocalized(
502: locale, simpleDateFormat.toPattern());
503: }
504: if (dateTimeFormat instanceof SimpleDateFormat) {
505: SimpleDateFormat simpleDateFormat = (SimpleDateFormat) dateTimeFormat;
506: dateTimePattern = convertDateFormatStringToLocalized(
507: locale, simpleDateFormat.toPattern());
508: }
509:
510: item = new DateFormatCacheItem(locale, datePattern,
511: dateTimePattern);
512: dateFormatStrings.put(item.key, item);
513: } else {
514: datePattern = item.dateFormat;
515: dateTimePattern = item.dateTimeFormat;
516: //System.err.println("DateTime.getDateFormatString cache hit");
517: }
518: }
519:
520: if (dateOnly) {
521: pattern = datePattern;
522: } else {
523: pattern = dateTimePattern;
524: }
525:
526: return pattern;
527: }
528:
529: /**
530: * Get the Date or DateTime format for a Locale. Called when the item is not cached.
531: * author David Lloyd
532: *
533: * @param locale The locale to get the format for. This may not be null
534: * @param p The format string to localize
535: * @return String formatted for the date
536: */
537: private static String convertDateFormatStringToLocalized(
538: Locale locale, String p) {
539: try {
540: FastStringBuffer fsb = new FastStringBuffer(16);
541: int n = p.length();
542: for (int i = 0; i < n; i++) {
543: char c = p.charAt(i);
544: switch (c) {
545: case 'M':
546: case 'd':
547: case 'y':
548: case 'h':
549: case 'H':
550: case 'k':
551: case 'K':
552: case 'm':
553: case 's': {
554: String s;
555: try {
556: s = Messages.getString(locale,
557: "datetime.format." + c + c);
558: fsb.append(s);
559: } catch (Exception e) {
560: fsb.append(c).append(c);
561: }
562: while (i < n - 1 && c == p.charAt(i + 1)) {
563: i++;
564: }
565: }
566: break;
567: default:
568: fsb.append(c);
569: break;
570: }
571: }
572: return fsb.toString();
573: } catch (Exception e) {
574: log
575: .warn(
576: "Exception parsing date format string to localized string",
577: e);
578: }
579: return "";
580: }
581:
582: /**
583: * DateFormat items in sDateFormatStrings hash table.
584: * author David Lloyd
585: */
586: static class DateFormatCacheItem {
587: public String key;
588: public String dateFormat;
589: public String dateTimeFormat;
590:
591: DateFormatCacheItem(Locale locale, String dateFormat,
592: String dateTimeFormat) {
593: key = deriveKey(locale);
594: this .dateFormat = dateFormat;
595: this .dateTimeFormat = dateTimeFormat;
596: }
597:
598: public String getKey() {
599: return key;
600: }
601:
602: static String deriveKey(Locale locale) {
603: return locale.getCountry() + "-" + locale.getLanguage();
604: }
605: }
606:
607: } /* DateTime */
|