View Javadoc

1   /*******************************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   *******************************************************************************/
19  package org.apache.commons.convert;
20  
21  import java.sql.Time;
22  import java.sql.Timestamp;
23  import java.text.DateFormat;
24  import java.text.ParseException;
25  import java.text.SimpleDateFormat;
26  import java.util.Calendar;
27  import java.util.Date;
28  import java.util.Locale;
29  import java.util.TimeZone;
30  
31  /** Date/time <code>Converter</code> classes. */
32  public class DateTimeConverters implements ConverterLoader {
33  
34      /**
35       * Calendar format string: <code>EEE MMM dd HH:mm:ss.SSS z yyyy</code>. 
36       */
37      public static final String CALENDAR_FORMAT = "EEE MMM dd HH:mm:ss.SSS z yyyy";
38      /**
39       * JDBC DATE format string: <code>yyyy-MM-dd</code>. 
40       */
41      public static final String JDBC_DATE_FORMAT = "yyyy-MM-dd";
42      /**
43       * JDBC TIME format string: <code>HH:mm:ss</code>. 
44       */
45      public static final String JDBC_TIME_FORMAT = "HH:mm:ss";
46  
47      /**
48       * Returns an initialized DateFormat object.
49       * 
50       * @param tz
51       * @return DateFormat object
52       */
53      protected static DateFormat toDateFormat(TimeZone tz) {
54          DateFormat df = new SimpleDateFormat(JDBC_DATE_FORMAT);
55          df.setTimeZone(tz);
56          return df;
57      }
58  
59      /**
60       * Returns an initialized DateFormat object.
61       * 
62       * @param dateTimeFormat
63       *            optional format string
64       * @param tz
65       * @param locale
66       *            can be null if dateTimeFormat is not null
67       * @return DateFormat object
68       */
69      protected static DateFormat toDateTimeFormat(String dateTimeFormat, TimeZone tz, Locale locale) {
70          DateFormat df = null;
71          if (Util.isEmpty(dateTimeFormat)) {
72              df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, locale);
73          } else {
74              df = new SimpleDateFormat(dateTimeFormat);
75          }
76          df.setTimeZone(tz);
77          return df;
78      }
79  
80      /**
81       * Returns an initialized DateFormat object.
82       * 
83       * @param tz
84       * @return DateFormat object
85       */
86      protected static DateFormat toTimeFormat(TimeZone tz) {
87          DateFormat df = new SimpleDateFormat(JDBC_TIME_FORMAT);
88          df.setTimeZone(tz);
89          return df;
90      }
91  
92      public void loadConverters() {
93          Converters.loadContainedConverters(DateTimeConverters.class);
94          Converters.registerConverter(new GenericDateToLong<java.util.Date>(java.util.Date.class));
95          Converters.registerConverter(new GenericDateToLong<java.sql.Date>(java.sql.Date.class));
96          Converters.registerConverter(new GenericDateToLong<java.sql.Time>(java.sql.Time.class));
97          Converters.registerConverter(new GenericDateToLong<java.sql.Timestamp>(java.sql.Timestamp.class));
98          Converters.registerConverter(new GenericSingletonToList<java.util.Calendar>(java.util.Calendar.class));
99          Converters.registerConverter(new GenericSingletonToList<java.util.Date>(java.util.Date.class));
100         Converters.registerConverter(new GenericSingletonToList<java.util.TimeZone>(java.util.TimeZone.class));
101         Converters.registerConverter(new GenericSingletonToList<java.sql.Date>(java.sql.Date.class));
102         Converters.registerConverter(new GenericSingletonToList<java.sql.Time>(java.sql.Time.class));
103         Converters.registerConverter(new GenericSingletonToList<java.sql.Timestamp>(java.sql.Timestamp.class));
104         Converters.registerConverter(new GenericSingletonToSet<java.util.Calendar>(java.util.Calendar.class));
105         Converters.registerConverter(new GenericSingletonToSet<java.util.Date>(java.util.Date.class));
106         Converters.registerConverter(new GenericSingletonToSet<java.util.TimeZone>(java.util.TimeZone.class));
107         Converters.registerConverter(new GenericSingletonToSet<java.sql.Date>(java.sql.Date.class));
108         Converters.registerConverter(new GenericSingletonToSet<java.sql.Time>(java.sql.Time.class));
109         Converters.registerConverter(new GenericSingletonToSet<java.sql.Timestamp>(java.sql.Timestamp.class));
110     }
111 
112     /**
113      * An object that converts a <code>Calendar</code> to a <code>Date</code>.
114      */
115     public static class CalendarToDate extends AbstractConverter<Calendar, Date> {
116         public CalendarToDate() {
117             super(Calendar.class, Date.class);
118         }
119 
120         @Override
121         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
122             return Util.instanceOf(sourceClass, this.getSourceClass()) && Date.class.equals(targetClass);
123         }
124 
125         public Date convert(Calendar obj) throws ConversionException {
126             return obj.getTime();
127         }
128     }
129 
130     /**
131      * An object that converts a <code>Calendar</code> to a <code>Long</code>.
132      */
133     public static class CalendarToLong extends AbstractConverter<Calendar, Long> {
134         public CalendarToLong() {
135             super(Calendar.class, Long.class);
136         }
137 
138         /**
139          * Returns the millisecond value of <code>obj</code>.
140          */
141         public Long convert(Calendar obj) throws ConversionException {
142             return obj.getTimeInMillis();
143         }
144     }
145 
146     /**
147      * An object that converts a <code>Calendar</code> to a <code>String</code>.
148      */
149     public static class CalendarToString extends AbstractLocalizedConverter<Calendar, String> {
150         public CalendarToString() {
151             super(Calendar.class, String.class);
152         }
153 
154         /**
155          * Converts <code>obj</code> to a <code>String</code> formatted as
156          * {@link DateTimeConverters#CALENDAR_FORMAT}. The returned string is
157          * referenced to the default time zone.
158          */
159         public String convert(Calendar obj) throws ConversionException {
160             DateFormat df = new SimpleDateFormat(CALENDAR_FORMAT);
161             df.setCalendar(obj);
162             return df.format(obj.getTime());
163         }
164 
165         /**
166          * Converts <code>obj</code> to a <code>String</code> using the supplied
167          * locale, time zone, and format string. If <code>formatString</code> is
168          * <code>null</code>, the string is formatted as
169          * {@link DateTimeConverters#CALENDAR_FORMAT}.
170          */
171         public String convert(Calendar obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
172             DateFormat df = toDateTimeFormat(formatString == null ? CALENDAR_FORMAT : formatString, timeZone, locale);
173             df.setCalendar(obj);
174             return df.format(obj.getTime());
175         }
176     }
177 
178     /**
179      * An object that converts a <code>Calendar</code> to a <code>Timestamp</code>.
180      */
181     public static class CalendarToTimestamp extends AbstractConverter<Calendar, Timestamp> {
182         public CalendarToTimestamp() {
183             super(Calendar.class, Timestamp.class);
184         }
185 
186         @Override
187         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
188             return Util.instanceOf(sourceClass, this.getSourceClass()) && Timestamp.class.equals(targetClass);
189         }
190 
191         public Timestamp convert(Calendar obj) throws ConversionException {
192             return new Timestamp(obj.getTimeInMillis());
193         }
194     }
195 
196 
197     /**
198      * An object that converts a <code>Date</code> to a <code>Calendar</code>.
199      */
200     public static class DateToCalendar extends GenericLocalizedConverter<Date, Calendar> {
201         public DateToCalendar() {
202             super(Date.class, Calendar.class);
203         }
204 
205         public Calendar convert(Date obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
206             Calendar cal = Calendar.getInstance(timeZone, locale);
207             cal.setTime(obj);
208             return cal;
209         }
210     }
211 
212     /**
213      * An object that converts a <code>java.util.Date</code> to a
214      * <code>java.sql.Date</code>.
215      */
216     public static class DateToSqlDate extends AbstractConverter<Date, java.sql.Date> {
217         public DateToSqlDate() {
218             super(Date.class, java.sql.Date.class);
219         }
220 
221         @Override
222         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
223             return (java.util.Date.class.equals(sourceClass) || java.sql.Timestamp.class.equals(sourceClass)) && java.sql.Date.class.equals(targetClass);
224         }
225 
226         /**
227          * Returns <code>obj</code> converted to a <code>java.sql.Date</code>.
228          */
229         @SuppressWarnings("deprecation")
230         public java.sql.Date convert(Date obj) throws ConversionException {
231             Calendar cal = Calendar.getInstance();
232             cal.setTimeInMillis(obj.getTime());
233             return new java.sql.Date(cal.get(Calendar.YEAR) - 1900, cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH));
234         }
235     }
236 
237     /**
238      * An object that converts a <code>java.util.Date</code> to a
239      * <code>java.sql.Time</code>.
240      */
241     public static class DateToSqlTime extends AbstractConverter<java.util.Date, java.sql.Time> {
242         public DateToSqlTime() {
243             super(Date.class, java.sql.Time.class);
244         }
245 
246         @Override
247         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
248             return sourceClass == this.getSourceClass() && targetClass == this.getTargetClass();
249         }
250 
251         @SuppressWarnings("deprecation")
252         public java.sql.Time convert(Date obj) throws ConversionException {
253             Calendar cal = Calendar.getInstance();
254             cal.setTimeInMillis(obj.getTime());
255             return new java.sql.Time(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
256         }
257     }
258 
259     /**
260      * An object that converts a <code>java.util.Date</code> to a
261      * <code>String</code>.
262      */
263     public static class DateToString extends AbstractLocalizedConverter<Date, String> {
264         public DateToString() {
265             super(Date.class, String.class);
266         }
267 
268         @Override
269         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
270             return Date.class.equals(sourceClass) && String.class.equals(targetClass);
271         }
272 
273         /**
274          * Converts <code>obj</code> to a <code>String</code> formatted as
275          * {@link DateTimeConverters#CALENDAR_FORMAT}. The returned string is
276          * referenced to the default time zone.
277          */
278         public String convert(Date obj) throws ConversionException {
279             DateFormat df = new SimpleDateFormat(CALENDAR_FORMAT);
280             return df.format(obj);
281         }
282 
283         /**
284          * Converts <code>obj</code> to a <code>String</code> using the supplied
285          * locale, time zone, and format string. If <code>formatString</code> is
286          * <code>null</code>, the string is formatted as
287          * {@link DateTimeConverters#CALENDAR_FORMAT}.
288          */
289         public String convert(Date obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
290             DateFormat df = toDateTimeFormat(formatString == null ? CALENDAR_FORMAT : formatString, timeZone, locale);
291             return df.format(obj);
292         }
293     }
294 
295     /**
296      * An object that converts a <code>java.util.Date</code> to a
297      * <code>java.sql.Timestamp</code>.
298      */
299     public static class DateToTimestamp extends AbstractConverter<Date, java.sql.Timestamp> {
300         public DateToTimestamp() {
301             super(Date.class, java.sql.Timestamp.class);
302         }
303 
304         @Override
305         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
306             return (java.util.Date.class.equals(sourceClass) || java.sql.Timestamp.class.equals(sourceClass)) && java.sql.Timestamp.class.equals(targetClass);
307         }
308 
309         /**
310          * Returns <code>obj</code> converted to a <code>java.sql.Timestamp</code>.
311          */
312         public java.sql.Timestamp convert(Date obj) throws ConversionException {
313             return new java.sql.Timestamp(obj.getTime());
314         }
315     }
316 
317     /**
318      * An object that converts a <code>java.util.Date</code> (and its subclasses) to a
319      * <code>Long</code>.
320      */
321     public static class GenericDateToLong<S extends Date> extends AbstractConverter<S, Long> {
322         public GenericDateToLong(Class<S> source) {
323             super(source, Long.class);
324         }
325 
326         /**
327          * Returns the millisecond value of <code>obj</code>.
328          */
329         public Long convert(S obj) throws ConversionException {
330             return obj.getTime();
331         }
332     }
333 
334     public static abstract class GenericLocalizedConverter<S, T> extends AbstractLocalizedConverter<S, T> {
335         protected GenericLocalizedConverter(Class<S> sourceClass, Class<T> targetClass) {
336             super(sourceClass, targetClass);
337         }
338 
339         public T convert(S obj) throws ConversionException {
340             return convert(obj, Locale.getDefault(), TimeZone.getDefault(), null);
341         }
342 
343         public T convert(S obj, Locale locale, TimeZone timeZone) throws ConversionException {
344             return convert(obj, locale, timeZone, null);
345         }
346     }
347 
348     /**
349      * An object that converts a <code>Long</code> to a
350      * <code>Calendar</code>.
351      */
352     public static class LongToCalendar extends AbstractLocalizedConverter<Long, Calendar> {
353         public LongToCalendar() {
354             super(Long.class, Calendar.class);
355         }
356 
357         /**
358          * Returns <code>obj</code> converted to a <code>Calendar</code>,
359          * initialized with the default locale and time zone.
360          */
361         public Calendar convert(Long obj) throws ConversionException {
362             Calendar cal = Calendar.getInstance();
363             cal.setTimeInMillis(obj);
364             return cal;
365         }
366 
367         /**
368          * Returns <code>obj</code> converted to a <code>Calendar</code>,
369          * initialized with the specified locale and time zone. The
370          * <code>formatString</code> parameter is ignored.
371          */
372         public Calendar convert(Long obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
373             Calendar cal = Calendar.getInstance(timeZone, locale);
374             cal.setTimeInMillis(obj);
375             return cal;
376         }
377     }
378 
379     /**
380      * An object that converts a <code>Long</code> to a
381      * <code>java.util.Date</code>.
382      */
383     public static class LongToDate extends AbstractConverter<Long, Date> {
384         public LongToDate() {
385             super(Long.class, Date.class);
386         }
387 
388         @Override
389         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
390             return Long.class.equals(sourceClass) && Date.class.equals(targetClass);
391         }
392 
393         /**
394          * Returns <code>obj</code> converted to a <code>java.util.Date</code>.
395          */
396         public Date convert(Long obj) throws ConversionException {
397             return new Date(obj.longValue());
398         }
399     }
400 
401     /**
402      * An object that converts a <code>Long</code> to a
403      * <code>java.sql.Date</code>.
404      */
405     public static class LongToSqlDate extends AbstractConverter<Long, java.sql.Date> {
406         public LongToSqlDate() {
407             super(Long.class, java.sql.Date.class);
408         }
409 
410         @Override
411         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
412             return Long.class.equals(sourceClass) && java.sql.Date.class.equals(targetClass);
413         }
414 
415         /**
416          * Returns <code>obj</code> converted to a <code>java.sql.Date</code>.
417          */
418         public java.sql.Date convert(Long obj) throws ConversionException {
419             return new java.sql.Date(obj.longValue());
420         }
421     }
422 
423     /**
424      * An object that converts a <code>Long</code> to a
425      * <code>java.sql.Time</code>.
426      */
427     public static class LongToSqlTime extends AbstractConverter<Long, java.sql.Time> {
428         public LongToSqlTime() {
429             super(Long.class, java.sql.Time.class);
430         }
431 
432         @Override
433         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
434             return Long.class.equals(sourceClass) && java.sql.Time.class.equals(targetClass);
435         }
436 
437         /**
438          * Returns <code>obj</code> converted to a <code>java.sql.Time</code>.
439          */
440         public java.sql.Time convert(Long obj) throws ConversionException {
441             return new java.sql.Time(obj.longValue());
442         }
443     }
444 
445     /**
446      * An object that converts a <code>Long</code> to a
447      * <code>java.sql.Timestamp</code>.
448      */
449     public static class LongToTimestamp extends AbstractConverter<Long, java.sql.Timestamp> {
450         public LongToTimestamp() {
451             super(Long.class, java.sql.Timestamp.class);
452         }
453 
454         @Override
455         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
456             return Long.class.equals(sourceClass) && java.sql.Timestamp.class.equals(targetClass);
457         }
458 
459         /**
460          * Returns <code>obj</code> converted to a <code>java.sql.Timestamp</code>.
461          */
462         public java.sql.Timestamp convert(Long obj) throws ConversionException {
463             return new java.sql.Timestamp(obj.longValue());
464         }
465     }
466 
467     /**
468      * An object that converts a <code>java.sql.Date</code> to a
469      * <code>java.util.Date</code>.
470      */
471     public static class SqlDateToDate extends AbstractConverter<java.sql.Date, Date> {
472         public SqlDateToDate() {
473             super(java.sql.Date.class, Date.class);
474         }
475 
476         @Override
477         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
478             return java.sql.Date.class.equals(sourceClass) && java.util.Date.class.equals(targetClass);
479         }
480 
481         /**
482          * Returns <code>obj</code> converted to a <code>java.util.Date</code>.
483          */
484         public Date convert(java.sql.Date obj) throws ConversionException {
485             return new Date(obj.getTime());
486         }
487     }
488 
489     /**
490      * An object that converts a <code>java.sql.Date</code> to a
491      * <code>String</code>.
492      */
493     public static class SqlDateToString extends AbstractLocalizedConverter<java.sql.Date, String> {
494         public SqlDateToString() {
495             super(java.sql.Date.class, String.class);
496         }
497 
498         @Override
499         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
500             return java.sql.Date.class.equals(sourceClass) && String.class.equals(targetClass);
501         }
502 
503         public String convert(java.sql.Date obj) throws ConversionException {
504             return obj.toString();
505         }
506 
507         /**
508          * Converts <code>obj</code> to a <code>String</code> using the supplied
509          * time zone. The <code>formatString</code> parameter is
510          * ignored. The returned string is formatted as
511          * {@link DateTimeConverters#JDBC_DATE_FORMAT}.
512          */
513         public String convert(java.sql.Date obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
514             DateFormat df = toDateFormat(timeZone);
515             return df.format(obj);
516         }
517     }
518 
519     /**
520      * An object that converts a <code>java.sql.Date</code> to a
521      * <code>java.sql.Timestamp</code>.
522      */
523     public static class SqlDateToTimestamp extends AbstractConverter<java.sql.Date, java.sql.Timestamp> {
524         public SqlDateToTimestamp() {
525             super(java.sql.Date.class, java.sql.Timestamp.class);
526         }
527 
528         @Override
529         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
530             return java.sql.Date.class.equals(sourceClass) && java.sql.Timestamp.class.equals(targetClass);
531         }
532 
533         /**
534          * Returns <code>obj</code> converted to a <code>java.sql.Timestamp</code>.
535          */
536         public java.sql.Timestamp convert(java.sql.Date obj) throws ConversionException {
537             return new java.sql.Timestamp(obj.getTime());
538         }
539     }
540 
541     /**
542      * An object that converts a <code>java.sql.Time</code> to a
543      * <code>String</code>.
544      */
545     public static class SqlTimeToString extends AbstractLocalizedConverter<java.sql.Time, String> {
546         public SqlTimeToString() {
547             super(java.sql.Time.class, String.class);
548         }
549 
550         @Override
551         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
552             return java.sql.Time.class.equals(sourceClass) && String.class.equals(targetClass);
553         }
554 
555         public String convert(java.sql.Time obj) throws ConversionException {
556             return obj.toString();
557         }
558 
559         /**
560          * Converts <code>obj</code> to a <code>String</code> using the supplied
561          * time zone. The <code>formatString</code> parameter is
562          * ignored. The returned string is formatted as
563          * {@link DateTimeConverters#JDBC_TIME_FORMAT}.
564          */
565         public String convert(java.sql.Time obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
566             DateFormat df = toTimeFormat(timeZone);
567             return df.format(obj);
568         }
569     }
570 
571     /**
572      * An object that converts a <code>String</code> to a
573      * <code>java.util.Calendar</code>.
574      */
575     public static class StringToCalendar extends AbstractLocalizedConverter<String, Calendar> {
576         public StringToCalendar() {
577             super(String.class, Calendar.class);
578         }
579 
580         /**
581          * Converts <code>obj</code> to a <code>java.util.Calendar</code> initialized to
582          * the default locale and time zone. The string must be formatted as
583          * {@link DateTimeConverters#CALENDAR_FORMAT}.
584          */
585         public Calendar convert(String obj) throws ConversionException {
586             try {
587                 DateFormat df = new SimpleDateFormat(CALENDAR_FORMAT);
588                 Calendar cal = Calendar.getInstance();
589                 cal.setTime(df.parse(obj));
590                 return cal;
591             } catch (ParseException e) {
592                 throw new ConversionException(e);
593             }
594         }
595 
596         /**
597          * Converts <code>obj</code> to a <code>java.util.Calendar</code> initialized to
598          * the supplied locale and time zone. If <code>formatString</code> is
599          * <code>null</code>, the string is formatted as
600          * {@link DateTimeConverters#CALENDAR_FORMAT}.
601          */
602         public Calendar convert(String obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
603             DateFormat df = toDateTimeFormat(formatString == null ? CALENDAR_FORMAT : formatString, timeZone, locale);
604             try {
605                 Date date = df.parse(obj);
606                 Calendar cal = Calendar.getInstance(timeZone, locale);
607                 cal.setTimeInMillis(date.getTime());
608                 return cal;
609             } catch (ParseException e) {
610                 throw new ConversionException(e);
611             }
612         }
613     }
614 
615     /**
616      * An object that converts a <code>String</code> to a
617      * <code>java.util.Date</code>.
618      */
619     public static class StringToDate extends AbstractLocalizedConverter<String, Date> {
620         public StringToDate() {
621             super(String.class, Date.class);
622         }
623 
624         @Override
625         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
626             return String.class.equals(sourceClass) && Date.class.equals(targetClass);
627         }
628 
629         /**
630          * Converts <code>obj</code> to a <code>java.util.Date</code>.
631          * The string must be formatted as
632          * {@link DateTimeConverters#CALENDAR_FORMAT}.
633          */
634         public Date convert(String obj) throws ConversionException {
635             try {
636                 DateFormat df = new SimpleDateFormat(CALENDAR_FORMAT);
637                 return df.parse(obj);
638             } catch (ParseException e) {
639                 throw new ConversionException(e);
640             }
641         }
642 
643         /**
644          * Converts <code>obj</code> to a <code>java.util.Date</code>. If
645          * <code>formatString</code> is <code>null</code>, the string is formatted as
646          * {@link DateTimeConverters#CALENDAR_FORMAT}.
647          */
648         public Date convert(String obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
649             DateFormat df = toDateTimeFormat(formatString == null ? CALENDAR_FORMAT : formatString, timeZone, locale);
650             try {
651                 return df.parse(obj);
652             } catch (ParseException e) {
653                 throw new ConversionException(e);
654             }
655         }
656     }
657 
658     /**
659      * An object that converts a <code>String</code> to a
660      * <code>java.sql.Date</code>.
661      */
662     public static class StringToSqlDate extends AbstractLocalizedConverter<String, java.sql.Date> {
663         public StringToSqlDate() {
664             super(String.class, java.sql.Date.class);
665         }
666 
667         @Override
668         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
669             return String.class.equals(sourceClass) && java.sql.Date.class.equals(targetClass);
670         }
671 
672         public java.sql.Date convert(String obj) throws ConversionException {
673             return java.sql.Date.valueOf(obj);
674         }
675 
676         /**
677          * Converts <code>obj</code> to a <code>java.sql.Date</code> using the supplied
678          * time zone. The <code>locale</code> and <code>formatString</code> parameters are
679          * ignored. The string must be formatted as
680          * {@link DateTimeConverters#JDBC_DATE_FORMAT}.
681          */
682         public java.sql.Date convert(String obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
683             DateFormat df = toDateFormat(timeZone);
684             try {
685                 return new java.sql.Date(df.parse(obj).getTime());
686             } catch (ParseException e) {
687                 throw new ConversionException(e);
688             }
689         }
690     }
691 
692     /**
693      * An object that converts a <code>String</code> to a
694      * <code>java.sql.Time</code>.
695      */
696     public static class StringToSqlTime extends AbstractLocalizedConverter<String, java.sql.Time> {
697         public StringToSqlTime() {
698             super(String.class, java.sql.Time.class);
699         }
700 
701         @Override
702         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
703             return String.class.equals(sourceClass) && java.sql.Time.class.equals(targetClass);
704         }
705 
706         public java.sql.Time convert(String obj) throws ConversionException {
707             return java.sql.Time.valueOf(obj);
708         }
709 
710         /**
711          * Converts <code>obj</code> to a <code>java.sql.Time</code> using the supplied
712          * time zone. The <code>locale</code> and <code>formatString</code> parameters are
713          * ignored. The string must be formatted as
714          * {@link DateTimeConverters#JDBC_TIME_FORMAT}.
715          */
716         public Time convert(String obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
717             DateFormat df = toTimeFormat(timeZone);
718             try {
719                 return new java.sql.Time(df.parse(obj).getTime());
720             } catch (ParseException e) {
721                 throw new ConversionException(e);
722             }
723         }
724     }
725 
726     /**
727      * An object that converts a <code>String</code> to a
728      * <code>java.sql.Timestamp</code>.
729      */
730     public static class StringToTimestamp extends AbstractLocalizedConverter<String, java.sql.Timestamp> {
731         public StringToTimestamp() {
732             super(String.class, java.sql.Timestamp.class);
733         }
734 
735         @Override
736         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
737             return String.class.equals(sourceClass) && java.sql.Timestamp.class.equals(targetClass);
738         }
739 
740         public Timestamp convert(String obj) throws ConversionException {
741             return java.sql.Timestamp.valueOf(obj);
742         }
743 
744         /**
745          * Converts <code>obj</code> to a <code>java.sql.Timestamp</code>.
746          * <p>Note that the string representation is referenced to the <code>timeZone</code>
747          * argument, not UTC. The <code>Timestamp</code> that is returned is adjusted to UTC.
748          * This behavior is intended to accommodate user-entered timestamps, where users are
749          * accustomed to using their own time zone.</p>
750          * </p>
751          */
752         public java.sql.Timestamp convert(String obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
753             try {
754                 // The String is referenced to the time zone represented by the timeZone
755                 // argument, but the parsing code assumes a reference to UTC. So, we need
756                 // to "adjust" the parsed Timestamp's value.
757                 Timestamp parsedStamp = Timestamp.valueOf(obj);
758                 Calendar cal = Calendar.getInstance(timeZone, locale);
759                 cal.setTime(parsedStamp);
760                 cal.add(Calendar.MILLISECOND, 0 - timeZone.getOffset(parsedStamp.getTime()));
761                 Timestamp result = new Timestamp(cal.getTimeInMillis());
762                 result.setNanos(parsedStamp.getNanos());
763                 return result;
764             } catch (Exception e) {
765                 throw new ConversionException(e);
766             }
767         }
768     }
769 
770     /**
771      * An object that converts a <code>String</code> ID to a
772      * <code>java.util.TimeZone</code>.
773      */
774     public static class StringToTimeZone extends AbstractConverter<String, TimeZone> {
775         public StringToTimeZone() {
776             super(String.class, TimeZone.class);
777         }
778 
779         public TimeZone convert(String obj) throws ConversionException {
780             return TimeZone.getTimeZone(obj);
781         }
782     }
783 
784     /**
785      * An object that converts a <code>java.sql.Timestamp</code> to a
786      * <code>java.util.Date</code>.
787      */
788     public static class TimestampToDate extends AbstractConverter<java.sql.Timestamp, Date> {
789         public TimestampToDate() {
790             super(java.sql.Timestamp.class, Date.class);
791         }
792 
793         @Override
794         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
795             return java.sql.Timestamp.class.equals(sourceClass) && java.util.Date.class.equals(targetClass);
796         }
797 
798         public Date convert(java.sql.Timestamp obj) throws ConversionException {
799             return new Timestamp(obj.getTime());
800         }
801     }
802 
803     /**
804      * An object that converts a <code>java.sql.Timestamp</code> to a
805      * <code>java.sql.Date</code>.
806      */
807     public static class TimestampToSqlDate extends AbstractConverter<java.sql.Timestamp, java.sql.Date> {
808         public TimestampToSqlDate() {
809             super(java.sql.Timestamp.class, java.sql.Date.class);
810         }
811 
812         @Override
813         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
814             return java.sql.Timestamp.class.equals(sourceClass) && java.sql.Date.class.equals(targetClass);
815         }
816 
817         public java.sql.Date convert(java.sql.Timestamp obj) throws ConversionException {
818             return new java.sql.Date(obj.getTime());
819         }
820     }
821 
822     /**
823      * An object that converts a <code>java.sql.Timestamp</code> to a
824      * <code>java.sql.Time</code>.
825      */
826     public static class TimestampToSqlTime extends AbstractConverter<java.sql.Timestamp, java.sql.Time> {
827         public TimestampToSqlTime() {
828             super(java.sql.Timestamp.class, java.sql.Time.class);
829         }
830 
831         @Override
832         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
833             return java.sql.Timestamp.class.equals(sourceClass) && java.sql.Time.class.equals(targetClass);
834         }
835 
836         public java.sql.Time convert(java.sql.Timestamp obj) throws ConversionException {
837             return new java.sql.Time(obj.getTime());
838         }
839     }
840 
841     /**
842      * An object that converts a <code>java.sql.Timestamp</code> to a
843      * <code>String</code>.
844      */
845     public static class TimestampToString extends AbstractLocalizedConverter<java.sql.Timestamp, String> {
846         public TimestampToString() {
847             super(java.sql.Timestamp.class, String.class);
848         }
849 
850         @Override
851         public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
852             return java.sql.Timestamp.class.equals(sourceClass) && String.class.equals(targetClass);
853         }
854 
855         public String convert(java.sql.Timestamp obj) throws ConversionException {
856             return obj.toString();
857         }
858 
859         /**
860          * Converts <code>obj</code> to a <code>String</code> using the supplied
861          * time zone.
862          * <p>Note that the string representation is referenced to the <code>timeZone</code>
863          * argument, not UTC. The <code>Timestamp</code> is adjusted to the specified
864          * time zone before conversion. This behavior is intended to accommodate user interfaces,
865          * where users are accustomed to viewing timestamps in their own time zone.</p>
866          * </p>
867          */
868         public String convert(Timestamp obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException {
869             try {
870                 // The Timestamp is referenced to UTC, but the String result needs to be
871                 // referenced to the time zone represented by the timeZone argument.
872                 // So, we need to "adjust" the Timestamp's value before conversion.
873                 Calendar cal = Calendar.getInstance(timeZone, locale);
874                 cal.setTime(obj);
875                 cal.add(Calendar.MILLISECOND, timeZone.getOffset(obj.getTime()));
876                 Timestamp result = new Timestamp(cal.getTimeInMillis());
877                 result.setNanos(obj.getNanos());
878                 return result.toString();
879             } catch (Exception e) {
880                 throw new ConversionException(e);
881             }
882         }
883     }
884 
885     /**
886      * An object that converts a <code>java.util.TimeZone</code> to a
887      * <code>String</code> ID.
888      */
889     public static class TimeZoneToString extends AbstractConverter<TimeZone, String> {
890         public TimeZoneToString() {
891             super(TimeZone.class, String.class);
892         }
893 
894         public String convert(TimeZone obj) throws ConversionException {
895             return obj.getID();
896         }
897     }
898 }