12
12
*
13
13
* @see <a href="http://www.w3.org/TR/NOTE-datetime">this specification</a>
14
14
*/
15
+ @ Deprecated // since 2.9
15
16
public class ISO8601Utils
16
17
{
17
- @ Deprecated // since 2.7
18
- private static final String GMT_ID = "GMT" ;
19
-
20
- /**
21
- * ID to represent the 'UTC' string, default timezone since Jackson 2.7
22
- *
23
- * @since 2.7
24
- */
25
- private static final String UTC_ID = "UTC" ;
26
-
27
- /**
28
- * The GMT timezone, prefetched to avoid more lookups.
29
- *
30
- * @deprecated Since 2.7 use {@link #TIMEZONE_UTC} instead
31
- */
32
- @ Deprecated
33
- private static final TimeZone TIMEZONE_GMT = TimeZone .getTimeZone (GMT_ID );
34
-
35
- /**
36
- * The UTC timezone, prefetched to avoid more lookups.
37
- *
38
- * @since 2.7
39
- */
40
- private static final TimeZone TIMEZONE_UTC = TimeZone .getTimeZone (UTC_ID );
18
+ protected final static int DEF_8601_LEN = "yyyy-MM-ddThh:mm:ss.SSS+00:00" .length ();
41
19
42
20
/**
43
21
* Timezone we use for 'Z' in ISO-8601 date/time values: since 2.7
44
22
* {@link #TIMEZONE_UTC}; with earlier versions up to 2.7 was {@link #TIMEZONE_GMT}.
45
23
*/
46
- private static final TimeZone TIMEZONE_Z = TIMEZONE_UTC ;
47
-
48
- /*
49
- /**********************************************************
50
- /* Static factories
51
- /**********************************************************
52
- */
53
-
54
- /**
55
- * Accessor for static GMT timezone instance.
56
- *
57
- * @deprecated since 2.6
58
- */
59
- @ Deprecated // since 2.6
60
- public static TimeZone timeZoneGMT () {
61
- return TIMEZONE_GMT ;
62
- }
24
+ private static final TimeZone TIMEZONE_Z = TimeZone .getTimeZone ("UTC" );
63
25
64
26
/*
65
27
/**********************************************************
@@ -74,7 +36,7 @@ public static TimeZone timeZoneGMT() {
74
36
* @return the date formatted as 'yyyy-MM-ddThh:mm:ssZ'
75
37
*/
76
38
public static String format (Date date ) {
77
- return format (date , false , TIMEZONE_UTC );
39
+ return format (date , false , TIMEZONE_Z );
78
40
}
79
41
80
42
/**
@@ -85,7 +47,12 @@ public static String format(Date date) {
85
47
* @return the date formatted as 'yyyy-MM-ddThh:mm:ss[.sss]Z'
86
48
*/
87
49
public static String format (Date date , boolean millis ) {
88
- return format (date , millis , TIMEZONE_UTC );
50
+ return format (date , millis , TIMEZONE_Z );
51
+ }
52
+
53
+ @ Deprecated // since 2.9
54
+ public static String format (Date date , boolean millis , TimeZone tz ) {
55
+ return format (date , millis , tz , Locale .US );
89
56
}
90
57
91
58
/**
@@ -95,45 +62,39 @@ public static String format(Date date, boolean millis) {
95
62
* @param millis true to include millis precision otherwise false
96
63
* @param tz timezone to use for the formatting (UTC will produce 'Z')
97
64
* @return the date formatted as yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm]
65
+ *
66
+ * @since 2.9
98
67
*/
99
- public static String format (Date date , boolean millis , TimeZone tz ) {
100
- Calendar calendar = new GregorianCalendar (tz , Locale . US );
68
+ public static String format (Date date , boolean millis , TimeZone tz , Locale loc ) {
69
+ Calendar calendar = new GregorianCalendar (tz , loc );
101
70
calendar .setTime (date );
102
71
103
72
// estimate capacity of buffer as close as we can (yeah, that's pedantic ;)
104
- int capacity = "yyyy-MM-ddThh:mm:ss" .length ();
105
- capacity += millis ? ".sss" .length () : 0 ;
106
- capacity += tz .getRawOffset () == 0 ? "Z" .length () : "+hh:mm" .length ();
107
- StringBuilder formatted = new StringBuilder (capacity );
108
-
109
- padInt (formatted , calendar .get (Calendar .YEAR ), "yyyy" .length ());
110
- formatted .append ('-' );
111
- padInt (formatted , calendar .get (Calendar .MONTH ) + 1 , "MM" .length ());
112
- formatted .append ('-' );
113
- padInt (formatted , calendar .get (Calendar .DAY_OF_MONTH ), "dd" .length ());
114
- formatted .append ('T' );
115
- padInt (formatted , calendar .get (Calendar .HOUR_OF_DAY ), "hh" .length ());
116
- formatted .append (':' );
117
- padInt (formatted , calendar .get (Calendar .MINUTE ), "mm" .length ());
118
- formatted .append (':' );
119
- padInt (formatted , calendar .get (Calendar .SECOND ), "ss" .length ());
73
+ StringBuilder sb = new StringBuilder (30 );
74
+ sb .append (String .format (
75
+ "%04d-%02d-%02dT%02d:%02d:%02d" ,
76
+ calendar .get (Calendar .YEAR ),
77
+ calendar .get (Calendar .MONTH ) + 1 ,
78
+ calendar .get (Calendar .DAY_OF_MONTH ),
79
+ calendar .get (Calendar .HOUR_OF_DAY ),
80
+ calendar .get (Calendar .MINUTE ),
81
+ calendar .get (Calendar .SECOND )
82
+ ));
120
83
if (millis ) {
121
- formatted .append ('.' );
122
- padInt (formatted , calendar .get (Calendar .MILLISECOND ), "sss" .length ());
84
+ sb .append (String .format (".%03d" , calendar .get (Calendar .MILLISECOND )));
123
85
}
124
86
125
87
int offset = tz .getOffset (calendar .getTimeInMillis ());
126
88
if (offset != 0 ) {
127
89
int hours = Math .abs ((offset / (60 * 1000 )) / 60 );
128
90
int minutes = Math .abs ((offset / (60 * 1000 )) % 60 );
129
- formatted .append (offset < 0 ? '-' : '+' );
130
- padInt (formatted , hours , "hh" .length ());
131
- formatted .append (':' );
132
- padInt (formatted , minutes , "mm" .length ());
91
+ sb .append (String .format ("%c%02d:%02d" ,
92
+ (offset < 0 ? '-' : '+' ),
93
+ hours , minutes ));
133
94
} else {
134
- formatted .append ('Z' );
95
+ sb .append ('Z' );
135
96
}
136
- return formatted .toString ();
97
+ return sb .toString ();
137
98
}
138
99
139
100
/*
@@ -286,11 +247,7 @@ public static Date parse(String date, ParsePosition pos) throws ParseException {
286
247
return calendar .getTime ();
287
248
// If we get a ParseException it'll already have the right message/offset.
288
249
// Other exception types can convert here.
289
- } catch (IndexOutOfBoundsException e ) {
290
- fail = e ;
291
- } catch (NumberFormatException e ) {
292
- fail = e ;
293
- } catch (IllegalArgumentException e ) {
250
+ } catch (Exception e ) {
294
251
fail = e ;
295
252
}
296
253
String input = (date == null ) ? null : ('"' + date + '"' );
@@ -350,21 +307,6 @@ private static int parseInt(String value, int beginIndex, int endIndex) throws N
350
307
return -result ;
351
308
}
352
309
353
- /**
354
- * Zero pad a number to a specified length
355
- *
356
- * @param buffer buffer to use for padding
357
- * @param value the integer value to pad if necessary.
358
- * @param length the length of the string we should zero pad
359
- */
360
- private static void padInt (StringBuilder buffer , int value , int length ) {
361
- String strValue = Integer .toString (value );
362
- for (int i = length - strValue .length (); i > 0 ; i --) {
363
- buffer .append ('0' );
364
- }
365
- buffer .append (strValue );
366
- }
367
-
368
310
/**
369
311
* Returns the index of the first character in the string that is not a digit, starting at offset.
370
312
*/
0 commit comments