KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > joda > time > format > ISODateTimeFormat


1 /*
2  * Copyright 2001-2006 Stephen Colebourne
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.joda.time.format;
17
18 import java.util.Collection JavaDoc;
19
20 import org.joda.time.DateTimeFieldType;
21 import org.joda.time.DateTimeZone;
22
23 /**
24  * Factory that creates instances of DateTimeFormatter for the ISO8601 standard.
25  * <p>
26  * Datetime formatting is performed by the {@link DateTimeFormatter} class.
27  * Three classes provide factory methods to create formatters, and this is one.
28  * The others are {@link DateTimeFormat} and {@link DateTimeFormatterBuilder}.
29  * <p>
30  * ISO8601 is the international standard for data interchange. It defines a
31  * framework, rather than an absolute standard. As a result this provider has a
32  * number of methods that represent common uses of the framework. The most common
33  * formats are {@link #date() date}, {@link #time() time}, and {@link #dateTime() dateTime}.
34  * <p>
35  * For example, to format a date time in ISO format:
36  * <pre>
37  * DateTime dt = new DateTime();
38  * DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
39  * String str = fmt.print(dt);
40  * </pre>
41  * <p>
42  * It is important to understand that these formatters are not linked to
43  * the <code>ISOChronology</code>. These formatters may be used with any
44  * chronology, however there may be certain side effects with more unusual
45  * chronologies. For example, the ISO formatters rely on dayOfWeek being
46  * single digit, dayOfMonth being two digit and dayOfYear being three digit.
47  * A chronology with a ten day week would thus cause issues. However, in
48  * general, it is safe to use these formatters with other chronologies.
49  * <p>
50  * ISODateTimeFormat is thread-safe and immutable, and the formatters it
51  * returns are as well.
52  *
53  * @author Brian S O'Neill
54  * @since 1.0
55  * @see DateTimeFormat
56  * @see DateTimeFormatterBuilder
57  */

58 public class ISODateTimeFormat {
59
60     //-----------------------------------------------------------------------
61
private static DateTimeFormatter
62         ye, // year element (yyyy)
63
mye, // monthOfYear element (-MM)
64
dme, // dayOfMonth element (-dd)
65
we, // weekyear element (xxxx)
66
wwe, // weekOfWeekyear element (-ww)
67
dwe, // dayOfWeek element (-ee)
68
dye, // dayOfYear element (-DDD)
69
hde, // hourOfDay element (HH)
70
mhe, // minuteOfHour element (:mm)
71
sme, // secondOfMinute element (:ss)
72
lse, // millisOfSecond element (.SSS)
73
fse, // fractionOfSecond element (.SSSSSSSSS)
74
ze, // zone offset element
75
lte, // literal 'T' element
76

77         //y, // year (same as year element)
78
ym, // year month
79
ymd, // year month day
80

81         //w, // weekyear (same as weekyear element)
82
ww, // weekyear week
83
wwd, // weekyear week day
84

85         //h, // hour (same as hour element)
86
hm, // hour minute
87
hms, // hour minute second
88
hmsl, // hour minute second millis
89
hmsf, // hour minute second fraction
90

91         dh, // date hour
92
dhm, // date hour minute
93
dhms, // date hour minute second
94
dhmsl, // date hour minute second millis
95
dhmsf, // date hour minute second fraction
96

97         //d, // date (same as ymd)
98
t, // time
99
tx, // time no millis
100
tt, // Ttime
101
ttx, // Ttime no millis
102
dt, // date time
103
dtx, // date time no millis
104

105         //wd, // week date (same as wwd)
106
wdt, // week date time
107
wdtx, // week date time no millis
108

109         od, // ordinal date (same as yd)
110
odt, // ordinal date time
111
odtx, // ordinal date time no millis
112

113         bd, // basic date
114
bt, // basic time
115
btx, // basic time no millis
116
btt, // basic Ttime
117
bttx, // basic Ttime no millis
118
bdt, // basic date time
119
bdtx, // basic date time no millis
120

121         bod, // basic ordinal date
122
bodt, // basic ordinal date time
123
bodtx, // basic ordinal date time no millis
124

125         bwd, // basic week date
126
bwdt, // basic week date time
127
bwdtx, // basic week date time no millis
128

129         dpe, // date parser element
130
tpe, // time parser element
131
dp, // date parser
132
ldp, // local date parser
133
tp, // time parser
134
ltp, // local time parser
135
dtp, // date time parser
136
dotp, // date optional time parser
137
ldotp; // local date optional time parser
138

139     /**
140      * Constructor.
141      *
142      * @since 1.1 (previously private)
143      */

144     protected ISODateTimeFormat() {
145         super();
146     }
147
148     //-----------------------------------------------------------------------
149
/**
150      * Returns a formatter that outputs only those fields specified.
151      * <p>
152      * This method examines the fields provided and returns an ISO-style
153      * formatter that best fits. This can be useful for outputting
154      * less-common ISO styles, such as YearMonth (YYYY-MM) or MonthDay (--MM-DD).
155      * <p>
156      * The list provided may have overlapping fields, such as dayOfWeek and
157      * dayOfMonth. In this case, the style is chosen based on the following
158      * list, thus in the example, the calendar style is chosen as dayOfMonth
159      * is higher in priority than dayOfWeek:
160      * <ul>
161      * <li>monthOfYear - calendar date style
162      * <li>dayOfYear - ordinal date style
163      * <li>weekOfWeekYear - week date style
164      * <li>dayOfMonth - calendar date style
165      * <li>dayOfWeek - week date style
166      * <li>year
167      * <li>weekyear
168      * </ul>
169      * The supported formats are:
170      * <pre>
171      * Extended Basic Fields
172      * 2005-03-25 20050325 year/monthOfYear/dayOfMonth
173      * 2005-03 2005-03 year/monthOfYear
174      * 2005--25 2005--25 year/dayOfMonth *
175      * 2005 2005 year
176      * --03-25 --0325 monthOfYear/dayOfMonth
177      * --03 --03 monthOfYear
178      * ---03 ---03 dayOfMonth
179      * 2005-084 2005084 year/dayOfYear
180      * -084 -084 dayOfYear
181      * 2005-W12-5 2005W125 weekyear/weekOfWeekyear/dayOfWeek
182      * 2005-W-5 2005W-5 weekyear/dayOfWeek *
183      * 2005-W12 2005W12 weekyear/weekOfWeekyear
184      * -W12-5 -W125 weekOfWeekyear/dayOfWeek
185      * -W12 -W12 weekOfWeekyear
186      * -W-5 -W-5 dayOfWeek
187      * 10:20:30.040 102030.040 hour/minute/second/milli
188      * 10:20:30 102030 hour/minute/second
189      * 10:20 1020 hour/minute
190      * 10 10 hour
191      * -20:30.040 -2030.040 minute/second/milli
192      * -20:30 -2030 minute/second
193      * -20 -20 minute
194      * --30.040 --30.040 second/milli
195      * --30 --30 second
196      * ---.040 ---.040 milli *
197      * 10-30.040 10-30.040 hour/second/milli *
198      * 10:20-.040 1020-.040 hour/minute/milli *
199      * 10-30 10-30 hour/second *
200      * 10--.040 10--.040 hour/milli *
201      * -20-.040 -20-.040 minute/milli *
202      * plus datetime formats like {date}T{time}
203      * </pre>
204      * * indiates that this is not an official ISO format and can be excluded
205      * by passing in <code>strictISO</code> as <code>true</code>.
206      *
207      * @param fields the fields to get a formatter for, not null,
208      * updated by the method call, which removes those fields built in the formatter
209      * @param extended true to use the extended format (with separators)
210      * @param strictISO true to stick exactly to ISO8601, false to include additional formats
211      * @return a suitable formatter
212      * @throws IllegalArgumentException if there is no format for the fields
213      * @since 1.1
214      */

215     public static DateTimeFormatter forFields(
216         Collection JavaDoc fields,
217         boolean extended,
218         boolean strictISO) {
219         
220         if (fields == null || fields.size() == 0) {
221             throw new IllegalArgumentException JavaDoc("The fields must not be null or empty");
222         }
223         int inputSize = fields.size();
224         boolean reducedPrec = false;
225         DateTimeFormatterBuilder bld = new DateTimeFormatterBuilder();
226         // date
227
if (fields.contains(DateTimeFieldType.monthOfYear())) {
228             reducedPrec = dateByMonth(bld, fields, extended, strictISO);
229         } else if (fields.contains(DateTimeFieldType.dayOfYear())) {
230             reducedPrec = dateByOrdinal(bld, fields, extended, strictISO);
231         } else if (fields.contains(DateTimeFieldType.weekOfWeekyear())) {
232             reducedPrec = dateByWeek(bld, fields, extended, strictISO);
233         } else if (fields.contains(DateTimeFieldType.dayOfMonth())) {
234             reducedPrec = dateByMonth(bld, fields, extended, strictISO);
235         } else if (fields.contains(DateTimeFieldType.dayOfWeek())) {
236             reducedPrec = dateByWeek(bld, fields, extended, strictISO);
237         } else if (fields.remove(DateTimeFieldType.year())) {
238             bld.append(yearElement());
239             reducedPrec = true;
240         } else if (fields.remove(DateTimeFieldType.weekyear())) {
241             bld.append(weekyearElement());
242             reducedPrec = true;
243         }
244         boolean datePresent = (fields.size() < inputSize);
245         
246         // time
247
time(bld, fields, extended, strictISO, reducedPrec, datePresent);
248         
249         // result
250
if (bld.canBuildFormatter() == false) {
251             throw new IllegalArgumentException JavaDoc("No valid format for fields: " + fields);
252         }
253         return bld.toFormatter();
254     }
255
256     //-----------------------------------------------------------------------
257
/**
258      * Creates a date using the calendar date format.
259      * Specification reference: 5.2.1.
260      *
261      * @param bld the builder
262      * @param fields the fields
263      * @param extended true to use extended format
264      * @param strictISO true to only allow ISO formats
265      * @return true if reduced precision
266      * @since 1.1
267      */

268     private static boolean dateByMonth(
269         DateTimeFormatterBuilder bld,
270         Collection JavaDoc fields,
271         boolean extended,
272         boolean strictISO) {
273         
274         boolean reducedPrec = false;
275         if (fields.remove(DateTimeFieldType.year())) {
276             bld.append(yearElement());
277             if (fields.remove(DateTimeFieldType.monthOfYear())) {
278                 if (fields.remove(DateTimeFieldType.dayOfMonth())) {
279                     // YYYY-MM-DD/YYYYMMDD
280
appendSeparator(bld, extended);
281                     bld.appendMonthOfYear(2);
282                     appendSeparator(bld, extended);
283                     bld.appendDayOfMonth(2);
284                 } else {
285                     // YYYY-MM/YYYY-MM
286
bld.appendLiteral('-');
287                     bld.appendMonthOfYear(2);
288                     reducedPrec = true;
289                 }
290             } else {
291                 if (fields.remove(DateTimeFieldType.dayOfMonth())) {
292                     // YYYY--DD/YYYY--DD (non-iso)
293
checkNotStrictISO(fields, strictISO);
294                     bld.appendLiteral('-');
295                     bld.appendLiteral('-');
296                     bld.appendDayOfMonth(2);
297                 } else {
298                     // YYYY/YYYY
299
reducedPrec = true;
300                 }
301             }
302             
303         } else if (fields.remove(DateTimeFieldType.monthOfYear())) {
304             bld.appendLiteral('-');
305             bld.appendLiteral('-');
306             bld.appendMonthOfYear(2);
307             if (fields.remove(DateTimeFieldType.dayOfMonth())) {
308                 // --MM-DD/--MMDD
309
appendSeparator(bld, extended);
310                 bld.appendDayOfMonth(2);
311             } else {
312                 // --MM/--MM
313
reducedPrec = true;
314             }
315         } else if (fields.remove(DateTimeFieldType.dayOfMonth())) {
316             // ---DD/---DD
317
bld.appendLiteral('-');
318             bld.appendLiteral('-');
319             bld.appendLiteral('-');
320             bld.appendDayOfMonth(2);
321         }
322         return reducedPrec;
323     }
324
325     //-----------------------------------------------------------------------
326
/**
327      * Creates a date using the ordinal date format.
328      * Specification reference: 5.2.2.
329      *
330      * @param bld the builder
331      * @param fields the fields
332      * @param extended true to use extended format
333      * @param strictISO true to only allow ISO formats
334      * @since 1.1
335      */

336     private static boolean dateByOrdinal(
337         DateTimeFormatterBuilder bld,
338         Collection JavaDoc fields,
339         boolean extended,
340         boolean strictISO) {
341         
342         boolean reducedPrec = false;
343         if (fields.remove(DateTimeFieldType.year())) {
344             bld.append(yearElement());
345             if (fields.remove(DateTimeFieldType.dayOfYear())) {
346                 // YYYY-DDD/YYYYDDD
347
appendSeparator(bld, extended);
348                 bld.appendDayOfYear(3);
349             } else {
350                 // YYYY/YYYY
351
reducedPrec = true;
352             }
353             
354         } else if (fields.remove(DateTimeFieldType.dayOfYear())) {
355             // -DDD/-DDD
356
bld.appendLiteral('-');
357             bld.appendDayOfYear(3);
358         }
359         return reducedPrec;
360     }
361
362     //-----------------------------------------------------------------------
363
/**
364      * Creates a date using the calendar date format.
365      * Specification reference: 5.2.3.
366      *
367      * @param bld the builder
368      * @param fields the fields
369      * @param extended true to use extended format
370      * @param strictISO true to only allow ISO formats
371      * @since 1.1
372      */

373     private static boolean dateByWeek(
374         DateTimeFormatterBuilder bld,
375         Collection JavaDoc fields,
376         boolean extended,
377         boolean strictISO) {
378         
379         boolean reducedPrec = false;
380         if (fields.remove(DateTimeFieldType.weekyear())) {
381             bld.append(weekyearElement());
382             if (fields.remove(DateTimeFieldType.weekOfWeekyear())) {
383                 appendSeparator(bld, extended);
384                 bld.appendLiteral('W');
385                 bld.appendWeekOfWeekyear(2);
386                 if (fields.remove(DateTimeFieldType.dayOfWeek())) {
387                     // YYYY-WWW-D/YYYYWWWD
388
appendSeparator(bld, extended);
389                     bld.appendDayOfWeek(1);
390                 } else {
391                     // YYYY-WWW/YYYY-WWW
392
reducedPrec = true;
393                 }
394             } else {
395                 if (fields.remove(DateTimeFieldType.dayOfWeek())) {
396                     // YYYY-W-D/YYYYW-D (non-iso)
397
checkNotStrictISO(fields, strictISO);
398                     appendSeparator(bld, extended);
399                     bld.appendLiteral('W');
400                     bld.appendLiteral('-');
401                     bld.appendDayOfWeek(1);
402                 } else {
403                     // YYYY/YYYY
404
reducedPrec = true;
405                 }
406             }
407             
408         } else if (fields.remove(DateTimeFieldType.weekOfWeekyear())) {
409             bld.appendLiteral('-');
410             bld.appendLiteral('W');
411             bld.appendWeekOfWeekyear(2);
412             if (fields.remove(DateTimeFieldType.dayOfWeek())) {
413                 // -WWW-D/-WWWD
414
appendSeparator(bld, extended);
415                 bld.appendDayOfWeek(1);
416             } else {
417                 // -WWW/-WWW
418
reducedPrec = true;
419             }
420         } else if (fields.remove(DateTimeFieldType.dayOfWeek())) {
421             // -W-D/-W-D
422
bld.appendLiteral('-');
423             bld.appendLiteral('W');
424             bld.appendLiteral('-');
425             bld.appendDayOfWeek(1);
426         }
427         return reducedPrec;
428     }
429
430     //-----------------------------------------------------------------------
431
/**
432      * Adds the time fields to the builder.
433      * Specification reference: 5.3.1.
434      *
435      * @param bld the builder
436      * @param fields the fields
437      * @param extended whether to use the extended format
438      * @param strictISO whether to be strict
439      * @param reducedPrec whether the date was reduced precision
440      * @param datePresent whether there was a date
441      * @since 1.1
442      */

443     private static void time(
444         DateTimeFormatterBuilder bld,
445         Collection JavaDoc fields,
446         boolean extended,
447         boolean strictISO,
448         boolean reducedPrec,
449         boolean datePresent) {
450         
451         boolean hour = fields.remove(DateTimeFieldType.hourOfDay());
452         boolean minute = fields.remove(DateTimeFieldType.minuteOfHour());
453         boolean second = fields.remove(DateTimeFieldType.secondOfMinute());
454         boolean milli = fields.remove(DateTimeFieldType.millisOfSecond());
455         if (!hour && !minute && !second && !milli) {
456             return;
457         }
458         if (hour || minute || second || milli) {
459             if (strictISO && reducedPrec) {
460                 throw new IllegalArgumentException JavaDoc("No valid ISO8601 format for fields because Date was reduced precision: " + fields);
461             }
462             if (datePresent) {
463                 bld.appendLiteral('T');
464             }
465         }
466         if (hour && minute && second || (hour && !second && !milli)) {
467             // OK - HMSm/HMS/HM/H - valid in combination with date
468
} else {
469             if (strictISO && datePresent) {
470                 throw new IllegalArgumentException JavaDoc("No valid ISO8601 format for fields because Time was truncated: " + fields);
471             }
472             if (!hour && (minute && second || (minute && !milli) || second)) {
473                 // OK - MSm/MS/M/Sm/S - valid ISO formats
474
} else {
475                 if (strictISO) {
476                     throw new IllegalArgumentException JavaDoc("No valid ISO8601 format for fields: " + fields);
477                 }
478             }
479         }
480         if (hour) {
481             bld.appendHourOfDay(2);
482         } else if (minute || second || milli) {
483             bld.appendLiteral('-');
484         }
485         if (extended && hour && minute) {
486             bld.appendLiteral(':');
487         }
488         if (minute) {
489             bld.appendMinuteOfHour(2);
490         } else if (second || milli) {
491             bld.appendLiteral('-');
492         }
493         if (extended && minute && second) {
494             bld.appendLiteral(':');
495         }
496         if (second) {
497             bld.appendSecondOfMinute(2);
498         } else if (milli) {
499             bld.appendLiteral('-');
500         }
501         if (milli) {
502             bld.appendLiteral('.');
503             bld.appendMillisOfSecond(3);
504         }
505     }
506
507     //-----------------------------------------------------------------------
508
/**
509      * Checks that the iso only flag is not set, throwing an exception if it is.
510      *
511      * @param fields the fields
512      * @param strictISO true if only ISO formats allowed
513      * @since 1.1
514      */

515     private static void checkNotStrictISO(Collection JavaDoc fields, boolean strictISO) {
516         if (strictISO) {
517             throw new IllegalArgumentException JavaDoc("No valid ISO8601 format for fields: " + fields);
518         }
519     }
520
521     /**
522      * Appends the separator if necessary.
523      *
524      * @param bld the builder
525      * @param extended whether to append the separator
526      * @param sep the separator
527      * @since 1.1
528      */

529     private static void appendSeparator(DateTimeFormatterBuilder bld, boolean extended) {
530         if (extended) {
531             bld.appendLiteral('-');
532         }
533     }
534
535     //-----------------------------------------------------------------------
536
/**
537      * Returns a generic ISO date parser for parsing dates with a possible zone.
538      * It accepts formats described by the following syntax:
539      * <pre>
540      * date = date-element ['T' offset]
541      * date-element = std-date-element | ord-date-element | week-date-element
542      * std-date-element = yyyy ['-' MM ['-' dd]]
543      * ord-date-element = yyyy ['-' DDD]
544      * week-date-element = xxxx '-W' ww ['-' e]
545      * offset = 'Z' | (('+' | '-') HH [':' mm [':' ss [('.' | ',') SSS]]])
546      * </pre>
547      */

548     public static DateTimeFormatter dateParser() {
549         if (dp == null) {
550             DateTimeParser tOffset = new DateTimeFormatterBuilder()
551                 .appendLiteral('T')
552                 .append(offsetElement()).toParser();
553             dp = new DateTimeFormatterBuilder()
554                 .append(dateElementParser())
555                 .appendOptional(tOffset)
556                 .toFormatter();
557         }
558         return dp;
559     }
560
561     /**
562      * Returns a generic ISO date parser for parsing local dates.
563      * This parser is initialised with the local (UTC) time zone.
564      * <p>
565      * It accepts formats described by the following syntax:
566      * <pre>
567      * date-element = std-date-element | ord-date-element | week-date-element
568      * std-date-element = yyyy ['-' MM ['-' dd]]
569      * ord-date-element = yyyy ['-' DDD]
570      * week-date-element = xxxx '-W' ww ['-' e]
571      * </pre>
572      * @since 1.3
573      */

574     public static DateTimeFormatter localDateParser() {
575         if (ldp == null) {
576             ldp = dateElementParser().withZone(DateTimeZone.UTC);
577         }
578         return ldp;
579     }
580
581     /**
582      * Returns a generic ISO date parser for parsing dates.
583      * It accepts formats described by the following syntax:
584      * <pre>
585      * date-element = std-date-element | ord-date-element | week-date-element
586      * std-date-element = yyyy ['-' MM ['-' dd]]
587      * ord-date-element = yyyy ['-' DDD]
588      * week-date-element = xxxx '-W' ww ['-' e]
589      * </pre>
590      */

591     public static DateTimeFormatter dateElementParser() {
592         if (dpe == null) {
593             dpe = new DateTimeFormatterBuilder()
594                 .append(null, new DateTimeParser[] {
595                     new DateTimeFormatterBuilder()
596                     .append(yearElement())
597                     .appendOptional
598                     (new DateTimeFormatterBuilder()
599                      .append(monthElement())
600                      .appendOptional(dayOfMonthElement().getParser())
601                      .toParser())
602                     .toParser(),
603                     new DateTimeFormatterBuilder()
604                     .append(weekyearElement())
605                     .append(weekElement())
606                     .appendOptional(dayOfWeekElement().getParser())
607                     .toParser(),
608                     new DateTimeFormatterBuilder()
609                     .append(yearElement())
610                     .append(dayOfYearElement())
611                     .toParser()
612                 })
613                 .toFormatter();
614         }
615         return dpe;
616     }
617
618     /**
619      * Returns a generic ISO time parser for parsing times with a possible zone.
620      * It accepts formats described by the following syntax:
621      * <pre>
622      * time = ['T'] time-element [offset]
623      * time-element = HH [minute-element] | [fraction]
624      * minute-element = ':' mm [second-element] | [fraction]
625      * second-element = ':' ss [fraction]
626      * fraction = ('.' | ',') digit+
627      * offset = 'Z' | (('+' | '-') HH [':' mm [':' ss [('.' | ',') SSS]]])
628      * </pre>
629      */

630     public static DateTimeFormatter timeParser() {
631         if (tp == null) {
632             tp = new DateTimeFormatterBuilder()
633                 .appendOptional(literalTElement().getParser())
634                 .append(timeElementParser())
635                 .appendOptional(offsetElement().getParser())
636                 .toFormatter();
637         }
638         return tp;
639     }
640
641     /**
642      * Returns a generic ISO time parser for parsing local times.
643      * This parser is initialised with the local (UTC) time zone.
644      * <p>
645      * It accepts formats described by the following syntax:
646      * <pre>
647      * time = ['T'] time-element
648      * time-element = HH [minute-element] | [fraction]
649      * minute-element = ':' mm [second-element] | [fraction]
650      * second-element = ':' ss [fraction]
651      * fraction = ('.' | ',') digit+
652      * </pre>
653      * @since 1.3
654      */

655     public static DateTimeFormatter localTimeParser() {
656         if (ltp == null) {
657             ltp = new DateTimeFormatterBuilder()
658                 .appendOptional(literalTElement().getParser())
659                 .append(timeElementParser())
660                 .toFormatter().withZone(DateTimeZone.UTC);
661         }
662         return ltp;
663     }
664
665     /**
666      * Returns a generic ISO time parser. It accepts formats described by
667      * the following syntax:
668      * <pre>
669      * time-element = HH [minute-element] | [fraction]
670      * minute-element = ':' mm [second-element] | [fraction]
671      * second-element = ':' ss [fraction]
672      * fraction = ('.' | ',') digit+
673      * </pre>
674      */

675     public static DateTimeFormatter timeElementParser() {
676         if (tpe == null) {
677             // Decimal point can be either '.' or ','
678
DateTimeParser decimalPoint = new DateTimeFormatterBuilder()
679                 .append(null, new DateTimeParser[] {
680                     new DateTimeFormatterBuilder()
681                     .appendLiteral('.')
682                     .toParser(),
683                     new DateTimeFormatterBuilder()
684                     .appendLiteral(',')
685                     .toParser()
686                 })
687                 .toParser();
688
689             tpe = new DateTimeFormatterBuilder()
690                 // time-element
691
.append(hourElement())
692                 .append
693                 (null, new DateTimeParser[] {
694                     new DateTimeFormatterBuilder()
695                     // minute-element
696
.append(minuteElement())
697                     .append
698                     (null, new DateTimeParser[] {
699                         new DateTimeFormatterBuilder()
700                         // second-element
701
.append(secondElement())
702                         // second fraction
703
.appendOptional(new DateTimeFormatterBuilder()
704                                         .append(decimalPoint)
705                                         .appendFractionOfSecond(1, 9)
706                                         .toParser())
707                         .toParser(),
708                         // minute fraction
709
new DateTimeFormatterBuilder()
710                         .append(decimalPoint)
711                         .appendFractionOfMinute(1, 9)
712                         .toParser(),
713                         null
714                     })
715                     .toParser(),
716                     // hour fraction
717
new DateTimeFormatterBuilder()
718                     .append(decimalPoint)
719                     .appendFractionOfHour(1, 9)
720                     .toParser(),
721                     null
722                 })
723                 .toFormatter();
724         }
725         return tpe;
726     }
727
728     /**
729      * Returns a generic ISO datetime parser which parses either a date or
730      * a time or both. It accepts formats described by the following syntax:
731      * <pre>
732      * datetime = time | date-opt-time
733      * time = 'T' time-element [offset]
734      * date-opt-time = date-element ['T' [time-element] [offset]]
735      * date-element = std-date-element | ord-date-element | week-date-element
736      * std-date-element = yyyy ['-' MM ['-' dd]]
737      * ord-date-element = yyyy ['-' DDD]
738      * week-date-element = xxxx '-W' ww ['-' e]
739      * time-element = HH [minute-element] | [fraction]
740      * minute-element = ':' mm [second-element] | [fraction]
741      * second-element = ':' ss [fraction]
742      * fraction = ('.' | ',') digit+
743      * offset = 'Z' | (('+' | '-') HH [':' mm [':' ss [('.' | ',') SSS]]])
744      * </pre>
745      */

746     public static DateTimeFormatter dateTimeParser() {
747         if (dtp == null) {
748             // This is different from the general time parser in that the 'T'
749
// is required.
750
DateTimeParser time = new DateTimeFormatterBuilder()
751                 .appendLiteral('T')
752                 .append(timeElementParser())
753                 .appendOptional(offsetElement().getParser())
754                 .toParser();
755             dtp = new DateTimeFormatterBuilder()
756                 .append(null, new DateTimeParser[] {time, dateOptionalTimeParser().getParser()})
757                 .toFormatter();
758         }
759         return dtp;
760     }
761
762     /**
763      * Returns a generic ISO datetime parser where the date is mandatory and
764      * the time is optional. This parser can parse zoned datetimes.
765      * It accepts formats described by the following syntax:
766      * <pre>
767      * date-opt-time = date-element ['T' [time-element] [offset]]
768      * date-element = std-date-element | ord-date-element | week-date-element
769      * std-date-element = yyyy ['-' MM ['-' dd]]
770      * ord-date-element = yyyy ['-' DDD]
771      * week-date-element = xxxx '-W' ww ['-' e]
772      * time-element = HH [minute-element] | [fraction]
773      * minute-element = ':' mm [second-element] | [fraction]
774      * second-element = ':' ss [fraction]
775      * fraction = ('.' | ',') digit+
776      * </pre>
777      * @since 1.3
778      */

779     public static DateTimeFormatter dateOptionalTimeParser() {
780         if (dotp == null) {
781             DateTimeParser timeOrOffset = new DateTimeFormatterBuilder()
782                 .appendLiteral('T')
783                 .appendOptional(timeElementParser().getParser())
784                 .appendOptional(offsetElement().getParser())
785                 .toParser();
786             dotp = new DateTimeFormatterBuilder()
787                 .append(dateElementParser())
788                 .appendOptional(timeOrOffset)
789                 .toFormatter();
790         }
791         return dotp;
792     }
793
794     /**
795      * Returns a generic ISO datetime parser where the date is mandatory and
796      * the time is optional. This parser only parses local datetimes.
797      * This parser is initialised with the local (UTC) time zone.
798      * <p>
799      * It accepts formats described by the following syntax:
800      * <pre>
801      * datetime = date-element ['T' time-element]
802      * date-element = std-date-element | ord-date-element | week-date-element
803      * std-date-element = yyyy ['-' MM ['-' dd]]
804      * ord-date-element = yyyy ['-' DDD]
805      * week-date-element = xxxx '-W' ww ['-' e]
806      * time-element = HH [minute-element] | [fraction]
807      * minute-element = ':' mm [second-element] | [fraction]
808      * second-element = ':' ss [fraction]
809      * fraction = ('.' | ',') digit+
810      * </pre>
811      * @since 1.3
812      */

813     public static DateTimeFormatter localDateOptionalTimeParser() {
814         if (ldotp == null) {
815             DateTimeParser time = new DateTimeFormatterBuilder()
816                 .appendLiteral('T')
817                 .append(timeElementParser())
818                 .toParser();
819             ldotp = new DateTimeFormatterBuilder()
820                 .append(dateElementParser())
821                 .appendOptional(time)
822                 .toFormatter().withZone(DateTimeZone.UTC);
823         }
824         return ldotp;
825     }
826
827     //-----------------------------------------------------------------------
828
/**
829      * Returns a formatter for a full date as four digit year, two digit month
830      * of year, and two digit day of month (yyyy-MM-dd).
831      *
832      * @return a formatter for yyyy-MM-dd
833      */

834     public static DateTimeFormatter date() {
835         return yearMonthDay();
836     }
837
838     /**
839      * Returns a formatter for a two digit hour of day, two digit minute of
840      * hour, two digit second of minute, three digit fraction of second, and
841      * time zone offset (HH:mm:ss.SSSZ).
842      * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
843      *
844      * @return a formatter for HH:mm:ss.SSSZ
845      */

846     public static DateTimeFormatter time() {
847         if (t == null) {
848             t = new DateTimeFormatterBuilder()
849                 .append(hourMinuteSecondMillis())
850                 .append(offsetElement())
851                 .toFormatter();
852         }
853         return t;
854     }
855
856     /**
857      * Returns a formatter for a two digit hour of day, two digit minute of
858      * hour, two digit second of minute, and time zone offset (HH:mm:ssZ).
859      * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
860      *
861      * @return a formatter for HH:mm:ssZ
862      */

863     public static DateTimeFormatter timeNoMillis() {
864         if (tx == null) {
865             tx = new DateTimeFormatterBuilder()
866                 .append(hourMinuteSecond())
867                 .append(offsetElement())
868                 .toFormatter();
869         }
870         return tx;
871     }
872
873     /**
874      * Returns a formatter for a two digit hour of day, two digit minute of
875      * hour, two digit second of minute, three digit fraction of second, and
876      * time zone offset prefixed by 'T' ('T'HH:mm:ss.SSSZ).
877      * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
878      *
879      * @return a formatter for 'T'HH:mm:ss.SSSZ
880      */

881     public static DateTimeFormatter tTime() {
882         if (tt == null) {
883             tt = new DateTimeFormatterBuilder()
884                 .append(literalTElement())
885                 .append(time())
886                 .toFormatter();
887         }
888         return tt;
889     }
890
891     /**
892      * Returns a formatter for a two digit hour of day, two digit minute of
893      * hour, two digit second of minute, and time zone offset prefixed
894      * by 'T' ('T'HH:mm:ssZ).
895      * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
896      *
897      * @return a formatter for 'T'HH:mm:ssZ
898      */

899     public static DateTimeFormatter tTimeNoMillis() {
900         if (ttx == null) {
901             ttx = new DateTimeFormatterBuilder()
902                 .append(literalTElement())
903                 .append(timeNoMillis())
904                 .toFormatter();
905         }
906         return ttx;
907     }
908
909     /**
910      * Returns a formatter that combines a full date and time, separated by a 'T'
911      * (yyyy-MM-dd'T'HH:mm:ss.SSSZ).
912      * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
913      *
914      * @return a formatter for yyyy-MM-dd'T'HH:mm:ss.SSSZ
915      */

916     public static DateTimeFormatter dateTime() {
917         if (dt == null) {
918             dt = new DateTimeFormatterBuilder()
919                 .append(date())
920                 .append(tTime())
921                 .toFormatter();
922         }
923         return dt;
924     }
925
926     /**
927      * Returns a formatter that combines a full date and time without millis,
928      * separated by a 'T' (yyyy-MM-dd'T'HH:mm:ssZ).
929      * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
930      *
931      * @return a formatter for yyyy-MM-dd'T'HH:mm:ssZ
932      */

933     public static DateTimeFormatter dateTimeNoMillis() {
934         if (dtx == null) {
935             dtx = new DateTimeFormatterBuilder()
936                 .append(date())
937                 .append(tTimeNoMillis())
938                 .toFormatter();
939         }
940         return dtx;
941     }
942
943     /**
944      * Returns a formatter for a full ordinal date, using a four
945      * digit year and three digit dayOfYear (yyyy-DDD).
946      *
947      * @return a formatter for yyyy-DDD
948      * @since 1.1
949      */

950     public static DateTimeFormatter ordinalDate() {
951         if (od == null) {
952             od = new DateTimeFormatterBuilder()
953                 .append(yearElement())
954                 .append(dayOfYearElement())
955                 .toFormatter();
956         }
957         return od;
958     }
959
960     /**
961      * Returns a formatter for a full ordinal date and time, using a four
962      * digit year and three digit dayOfYear (yyyy-DDD'T'HH:mm:ss.SSSZ).
963      * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
964      *
965      * @return a formatter for yyyy-DDD'T'HH:mm:ss.SSSZ
966      * @since 1.1
967      */

968     public static DateTimeFormatter ordinalDateTime() {
969         if (odt == null) {
970             odt = new DateTimeFormatterBuilder()
971                 .append(ordinalDate())
972                 .append(tTime())
973                 .toFormatter();
974         }
975         return odt;
976     }
977
978     /**
979      * Returns a formatter for a full ordinal date and time without millis,
980      * using a four digit year and three digit dayOfYear (yyyy-DDD'T'HH:mm:ssZ).
981      * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
982      *
983      * @return a formatter for yyyy-DDD'T'HH:mm:ssZ
984      * @since 1.1
985      */

986     public static DateTimeFormatter ordinalDateTimeNoMillis() {
987         if (odtx == null) {
988             odtx = new DateTimeFormatterBuilder()
989                 .append(ordinalDate())
990                 .append(tTimeNoMillis())
991                 .toFormatter();
992         }
993         return odtx;
994     }
995
996     /**
997      * Returns a formatter for a full date as four digit weekyear, two digit
998      * week of weekyear, and one digit day of week (xxxx-'W'ww-e).
999      *
1000     * @return a formatter for xxxx-'W'ww-e
1001     */

1002    public static DateTimeFormatter weekDate() {
1003        return weekyearWeekDay();
1004    }
1005
1006    /**
1007     * Returns a formatter that combines a full weekyear date and time,
1008     * separated by a 'T' (xxxx-'W'ww-e'T'HH:mm:ss.SSSZ).
1009     * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
1010     *
1011     * @return a formatter for xxxx-'W'ww-e'T'HH:mm:ss.SSSZ
1012     */

1013    public static DateTimeFormatter weekDateTime() {
1014        if (wdt == null) {
1015            wdt = new DateTimeFormatterBuilder()
1016                .append(weekDate())
1017                .append(tTime())
1018                .toFormatter();
1019        }
1020        return wdt;
1021    }
1022
1023    /**
1024     * Returns a formatter that combines a full weekyear date and time without millis,
1025     * separated by a 'T' (xxxx-'W'ww-e'T'HH:mm:ssZ).
1026     * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
1027     *
1028     * @return a formatter for xxxx-'W'ww-e'T'HH:mm:ssZ
1029     */

1030    public static DateTimeFormatter weekDateTimeNoMillis() {
1031        if (wdtx == null) {
1032            wdtx = new DateTimeFormatterBuilder()
1033                .append(weekDate())
1034                .append(tTimeNoMillis())
1035                .toFormatter();
1036        }
1037        return wdtx;
1038    }
1039
1040    //-----------------------------------------------------------------------
1041
/**
1042     * Returns a basic formatter for a full date as four digit year, two digit
1043     * month of year, and two digit day of month (yyyyMMdd).
1044     *
1045     * @return a formatter for yyyyMMdd
1046     */

1047    public static DateTimeFormatter basicDate() {
1048        if (bd == null) {
1049            bd = new DateTimeFormatterBuilder()
1050                .appendYear(4, 4)
1051                .appendMonthOfYear(2)
1052                .appendDayOfMonth(2)
1053                .toFormatter();
1054        }
1055        return bd;
1056    }
1057
1058    /**
1059     * Returns a basic formatter for a two digit hour of day, two digit minute
1060     * of hour, two digit second of minute, three digit millis, and time zone
1061     * offset (HHmmss.SSSZ).
1062     * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
1063     *
1064     * @return a formatter for HHmmss.SSSZ
1065     */

1066    public static DateTimeFormatter basicTime() {
1067        if (bt == null) {
1068            bt = new DateTimeFormatterBuilder()
1069                .appendHourOfDay(2)
1070                .appendMinuteOfHour(2)
1071                .appendSecondOfMinute(2)
1072                .appendLiteral('.')
1073                .appendMillisOfSecond(3)
1074                .appendTimeZoneOffset("Z", false, 2, 2)
1075                .toFormatter();
1076        }
1077        return bt;
1078    }
1079
1080    /**
1081     * Returns a basic formatter for a two digit hour of day, two digit minute
1082     * of hour, two digit second of minute, and time zone offset (HHmmssZ).
1083     * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
1084     *
1085     * @return a formatter for HHmmssZ
1086     */

1087    public static DateTimeFormatter basicTimeNoMillis() {
1088        if (btx == null) {
1089            btx = new DateTimeFormatterBuilder()
1090                .appendHourOfDay(2)
1091                .appendMinuteOfHour(2)
1092                .appendSecondOfMinute(2)
1093                .appendTimeZoneOffset("Z", false, 2, 2)
1094                .toFormatter();
1095        }
1096        return btx;
1097    }
1098
1099    /**
1100     * Returns a basic formatter for a two digit hour of day, two digit minute
1101     * of hour, two digit second of minute, three digit millis, and time zone
1102     * offset prefixed by 'T' ('T'HHmmss.SSSZ).
1103     * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
1104     *
1105     * @return a formatter for 'T'HHmmss.SSSZ
1106     */

1107    public static DateTimeFormatter basicTTime() {
1108        if (btt == null) {
1109            btt = new DateTimeFormatterBuilder()
1110                .append(literalTElement())
1111                .append(basicTime())
1112                .toFormatter();
1113        }
1114        return btt;
1115    }
1116
1117    /**
1118     * Returns a basic formatter for a two digit hour of day, two digit minute
1119     * of hour, two digit second of minute, and time zone offset prefixed by 'T'
1120     * ('T'HHmmssZ).
1121     * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
1122     *
1123     * @return a formatter for 'T'HHmmssZ
1124     */

1125    public static DateTimeFormatter basicTTimeNoMillis() {
1126        if (bttx == null) {
1127            bttx = new DateTimeFormatterBuilder()
1128                .append(literalTElement())
1129                .append(basicTimeNoMillis())
1130                .toFormatter();
1131        }
1132        return bttx;
1133    }
1134
1135    /**
1136     * Returns a basic formatter that combines a basic date and time, separated
1137     * by a 'T' (yyyyMMdd'T'HHmmss.SSSZ).
1138     * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
1139     *
1140     * @return a formatter for yyyyMMdd'T'HHmmss.SSSZ
1141     */

1142    public static DateTimeFormatter basicDateTime() {
1143        if (bdt == null) {
1144            bdt = new DateTimeFormatterBuilder()
1145                .append(basicDate())
1146                .append(basicTTime())
1147                .toFormatter();
1148        }
1149        return bdt;
1150    }
1151
1152    /**
1153     * Returns a basic formatter that combines a basic date and time without millis,
1154     * separated by a 'T' (yyyyMMdd'T'HHmmssZ).
1155     * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
1156     *
1157     * @return a formatter for yyyyMMdd'T'HHmmssZ
1158     */

1159    public static DateTimeFormatter basicDateTimeNoMillis() {
1160        if (bdtx == null) {
1161            bdtx = new DateTimeFormatterBuilder()
1162                .append(basicDate())
1163                .append(basicTTimeNoMillis())
1164                .toFormatter();
1165        }
1166        return bdtx;
1167    }
1168
1169    /**
1170     * Returns a formatter for a full ordinal date, using a four
1171     * digit year and three digit dayOfYear (yyyyDDD).
1172     *
1173     * @return a formatter for yyyyDDD
1174     * @since 1.1
1175     */

1176    public static DateTimeFormatter basicOrdinalDate() {
1177        if (bod == null) {
1178            bod = new DateTimeFormatterBuilder()
1179                .appendYear(4, 4)
1180                .appendDayOfYear(3)
1181                .toFormatter();
1182        }
1183        return bod;
1184    }
1185
1186    /**
1187     * Returns a formatter for a full ordinal date and time, using a four
1188     * digit year and three digit dayOfYear (yyyyDDD'T'HHmmss.SSSZ).
1189     * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
1190     *
1191     * @return a formatter for yyyyDDD'T'HHmmss.SSSZ
1192     * @since 1.1
1193     */

1194    public static DateTimeFormatter basicOrdinalDateTime() {
1195        if (bodt == null) {
1196            bodt = new DateTimeFormatterBuilder()
1197                .append(basicOrdinalDate())
1198                .append(basicTTime())
1199                .toFormatter();
1200        }
1201        return bodt;
1202    }
1203
1204    /**
1205     * Returns a formatter for a full ordinal date and time without millis,
1206     * using a four digit year and three digit dayOfYear (yyyyDDD'T'HHmmssZ).
1207     * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
1208     *
1209     * @return a formatter for yyyyDDD'T'HHmmssZ
1210     * @since 1.1
1211     */

1212    public static DateTimeFormatter basicOrdinalDateTimeNoMillis() {
1213        if (bodtx == null) {
1214            bodtx = new DateTimeFormatterBuilder()
1215                .append(basicOrdinalDate())
1216                .append(basicTTimeNoMillis())
1217                .toFormatter();
1218        }
1219        return bodtx;
1220    }
1221
1222    /**
1223     * Returns a basic formatter for a full date as four digit weekyear, two
1224     * digit week of weekyear, and one digit day of week (xxxx'W'wwe).
1225     *
1226     * @return a formatter for xxxx'W'wwe
1227     */

1228    public static DateTimeFormatter basicWeekDate() {
1229        if (bwd == null) {
1230            bwd = new DateTimeFormatterBuilder()
1231                .appendWeekyear(4, 4)
1232                .appendLiteral('W')
1233                .appendWeekOfWeekyear(2)
1234                .appendDayOfWeek(1)
1235                .toFormatter();
1236        }
1237        return bwd;
1238    }
1239
1240    /**
1241     * Returns a basic formatter that combines a basic weekyear date and time,
1242     * separated by a 'T' (xxxx'W'wwe'T'HHmmss.SSSZ).
1243     * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
1244     *
1245     * @return a formatter for xxxx'W'wwe'T'HHmmss.SSSZ
1246     */

1247    public static DateTimeFormatter basicWeekDateTime() {
1248        if (bwdt == null) {
1249            bwdt = new DateTimeFormatterBuilder()
1250                .append(basicWeekDate())
1251                .append(basicTTime())
1252                .toFormatter();
1253        }
1254        return bwdt;
1255    }
1256
1257    /**
1258     * Returns a basic formatter that combines a basic weekyear date and time
1259     * without millis, separated by a 'T' (xxxx'W'wwe'T'HHmmssZ).
1260     * The time zone offset is 'Z' for zero, and of the form '±HH:mm' for non-zero.
1261     *
1262     * @return a formatter for xxxx'W'wwe'T'HHmmssZ
1263     */

1264    public static DateTimeFormatter basicWeekDateTimeNoMillis() {
1265        if (bwdtx == null) {
1266            bwdtx = new DateTimeFormatterBuilder()
1267                .append(basicWeekDate())
1268                .append(basicTTimeNoMillis())
1269                .toFormatter();
1270        }
1271        return bwdtx;
1272    }
1273
1274    //-----------------------------------------------------------------------
1275
/**
1276     * Returns a formatter for a four digit year. (yyyy)
1277     *
1278     * @return a formatter for yyyy
1279     */

1280    public static DateTimeFormatter year() {
1281        return yearElement();
1282    }
1283
1284    /**
1285     * Returns a formatter for a four digit year and two digit month of
1286     * year. (yyyy-MM)
1287     *
1288     * @return a formatter for yyyy-MM
1289     */

1290    public static DateTimeFormatter yearMonth() {
1291        if (ym == null) {
1292            ym = new DateTimeFormatterBuilder()
1293                .append(yearElement())
1294                .append(monthElement())
1295                .toFormatter();
1296        }
1297        return ym;
1298    }
1299
1300    /**
1301     * Returns a formatter for a four digit year, two digit month of year, and
1302     * two digit day of month. (yyyy-MM-dd)
1303     *
1304     * @return a formatter for yyyy-MM-dd
1305     */

1306    public static DateTimeFormatter yearMonthDay() {
1307        if (ymd == null) {
1308            ymd = new DateTimeFormatterBuilder()
1309                .append(yearElement())
1310                .append(monthElement())
1311                .append(dayOfMonthElement())
1312                .toFormatter();
1313        }
1314        return ymd;
1315    }
1316
1317    /**
1318     * Returns a formatter for a four digit weekyear. (xxxx)
1319     *
1320     * @return a formatter for xxxx
1321     */

1322    public static DateTimeFormatter weekyear() {
1323        return weekyearElement();
1324    }
1325
1326    /**
1327     * Returns a formatter for a four digit weekyear and two digit week of
1328     * weekyear. (xxxx-'W'ww)
1329     *
1330     * @return a formatter for xxxx-'W'ww
1331     */

1332    public static DateTimeFormatter weekyearWeek() {
1333        if (ww == null) {
1334            ww = new DateTimeFormatterBuilder()
1335                .append(weekyearElement())
1336                .append(weekElement())
1337                .toFormatter();
1338        }
1339        return ww;
1340    }
1341
1342    /**
1343     * Returns a formatter for a four digit weekyear, two digit week of
1344     * weekyear, and one digit day of week. (xxxx-'W'ww-e)
1345     *
1346     * @return a formatter for xxxx-'W'ww-e
1347     */

1348    public static DateTimeFormatter weekyearWeekDay() {
1349        if (wwd == null) {
1350            wwd = new DateTimeFormatterBuilder()
1351                .append(weekyearElement())
1352                .append(weekElement())
1353                .append(dayOfWeekElement())
1354                .toFormatter();
1355        }
1356        return wwd;
1357    }
1358
1359    /**
1360     * Returns a formatter for a two digit hour of day. (HH)
1361     *
1362     * @return a formatter for HH
1363     */

1364    public static DateTimeFormatter hour() {
1365        return hourElement();
1366    }
1367
1368    /**
1369     * Returns a formatter for a two digit hour of day and two digit minute of
1370     * hour. (HH:mm)
1371     *
1372     * @return a formatter for HH:mm
1373     */

1374    public static DateTimeFormatter hourMinute() {
1375        if (hm == null) {
1376            hm = new DateTimeFormatterBuilder()
1377                .append(hourElement())
1378                .append(minuteElement())
1379                .toFormatter();
1380        }
1381        return hm;
1382    }
1383
1384    /**
1385     * Returns a formatter for a two digit hour of day, two digit minute of
1386     * hour, and two digit second of minute. (HH:mm:ss)
1387     *
1388     * @return a formatter for HH:mm:ss
1389     */

1390    public static DateTimeFormatter hourMinuteSecond() {
1391        if (hms == null) {
1392            hms = new DateTimeFormatterBuilder()
1393                .append(hourElement())
1394                .append(minuteElement())
1395                .append(secondElement())
1396                .toFormatter();
1397        }
1398        return hms;
1399    }
1400
1401    /**
1402     * Returns a formatter for a two digit hour of day, two digit minute of
1403     * hour, two digit second of minute, and three digit fraction of
1404     * second. (HH:mm:ss.SSS)
1405     *
1406     * @return a formatter for HH:mm:ss.SSS
1407     */

1408    public static DateTimeFormatter hourMinuteSecondMillis() {
1409        if (hmsl == null) {
1410            hmsl = new DateTimeFormatterBuilder()
1411                .append(hourElement())
1412                .append(minuteElement())
1413                .append(secondElement())
1414                .append(millisElement())
1415                .toFormatter();
1416        }
1417        return hmsl;
1418    }
1419
1420    /**
1421     * Returns a formatter for a two digit hour of day, two digit minute of
1422     * hour, two digit second of minute, and three digit fraction of
1423     * second. (HH:mm:ss.SSS)
1424     *
1425     * @return a formatter for HH:mm:ss.SSS
1426     */

1427    public static DateTimeFormatter hourMinuteSecondFraction() {
1428        if (hmsf == null) {
1429            hmsf = new DateTimeFormatterBuilder()
1430                .append(hourElement())
1431                .append(minuteElement())
1432                .append(secondElement())
1433                .append(fractionElement())
1434                .toFormatter();
1435        }
1436        return hmsf;
1437    }
1438
1439    /**
1440     * Returns a formatter that combines a full date and two digit hour of
1441     * day. (yyyy-MM-dd'T'HH)
1442     *
1443     * @return a formatter for yyyy-MM-dd'T'HH
1444     */

1445    public static DateTimeFormatter dateHour() {
1446        if (dh == null) {
1447            dh = new DateTimeFormatterBuilder()
1448                .append(date())
1449                .append(literalTElement())
1450                .append(hour())
1451                .toFormatter();
1452        }
1453        return dh;
1454    }
1455
1456    /**
1457     * Returns a formatter that combines a full date, two digit hour of day,
1458     * and two digit minute of hour. (yyyy-MM-dd'T'HH:mm)
1459     *
1460     * @return a formatter for yyyy-MM-dd'T'HH:mm
1461     */

1462    public static DateTimeFormatter dateHourMinute() {
1463        if (dhm == null) {
1464            dhm = new DateTimeFormatterBuilder()
1465                .append(date())
1466                .append(literalTElement())
1467                .append(hourMinute())
1468                .toFormatter();
1469        }
1470        return dhm;
1471    }
1472
1473    /**
1474     * Returns a formatter that combines a full date, two digit hour of day,
1475     * two digit minute of hour, and two digit second of
1476     * minute. (yyyy-MM-dd'T'HH:mm:ss)
1477     *
1478     * @return a formatter for yyyy-MM-dd'T'HH:mm:ss
1479     */

1480    public static DateTimeFormatter dateHourMinuteSecond() {
1481        if (dhms == null) {
1482            dhms = new DateTimeFormatterBuilder()
1483                .append(date())
1484                .append(literalTElement())
1485                .append(hourMinuteSecond())
1486                .toFormatter();
1487        }
1488        return dhms;
1489    }
1490
1491    /**
1492     * Returns a formatter that combines a full date, two digit hour of day,
1493     * two digit minute of hour, two digit second of minute, and three digit
1494     * fraction of second. (yyyy-MM-dd'T'HH:mm:ss.SSS)
1495     *
1496     * @return a formatter for yyyy-MM-dd'T'HH:mm:ss.SSS
1497     */

1498    public static DateTimeFormatter dateHourMinuteSecondMillis() {
1499        if (dhmsl == null) {
1500            dhmsl = new DateTimeFormatterBuilder()
1501                .append(date())
1502                .append(literalTElement())
1503                .append(hourMinuteSecondMillis())
1504                .toFormatter();
1505        }
1506        return dhmsl;
1507    }
1508
1509    /**
1510     * Returns a formatter that combines a full date, two digit hour of day,
1511     * two digit minute of hour, two digit second of minute, and three digit
1512     * fraction of second. (yyyy-MM-dd'T'HH:mm:ss.SSS)
1513     *
1514     * @return a formatter for yyyy-MM-dd'T'HH:mm:ss.SSS
1515     */

1516    public static DateTimeFormatter dateHourMinuteSecondFraction() {
1517        if (dhmsf == null) {
1518            dhmsf = new DateTimeFormatterBuilder()
1519                .append(date())
1520                .append(literalTElement())
1521                .append(hourMinuteSecondFraction())
1522                .toFormatter();
1523        }
1524        return dhmsf;
1525    }
1526
1527    //-----------------------------------------------------------------------
1528
private static DateTimeFormatter yearElement() {
1529        if (ye == null) {
1530            ye = new DateTimeFormatterBuilder()
1531                .appendYear(4, 9)
1532                .toFormatter();
1533        }
1534        return ye;
1535    }
1536
1537    private static DateTimeFormatter monthElement() {
1538        if (mye == null) {
1539            mye = new DateTimeFormatterBuilder()
1540                .appendLiteral('-')
1541                .appendMonthOfYear(2)
1542                .toFormatter();
1543        }
1544        return mye;
1545    }
1546
1547    private static DateTimeFormatter dayOfMonthElement() {
1548        if (dme == null) {
1549            dme = new DateTimeFormatterBuilder()
1550                .appendLiteral('-')
1551                .appendDayOfMonth(2)
1552                .toFormatter();
1553        }
1554        return dme;
1555    }
1556
1557    private static DateTimeFormatter weekyearElement() {
1558        if (we == null) {
1559            we = new DateTimeFormatterBuilder()
1560                .appendWeekyear(4, 9)
1561                .toFormatter();
1562        }
1563        return we;
1564    }
1565
1566    private static DateTimeFormatter weekElement() {
1567        if (wwe == null) {
1568            wwe = new DateTimeFormatterBuilder()
1569                .appendLiteral("-W")
1570                .appendWeekOfWeekyear(2)
1571                .toFormatter();
1572        }
1573        return wwe;
1574    }
1575
1576    private static DateTimeFormatter dayOfWeekElement() {
1577        if (dwe == null) {
1578            dwe = new DateTimeFormatterBuilder()
1579                .appendLiteral('-')
1580                .appendDayOfWeek(1)
1581                .toFormatter();
1582        }
1583        return dwe;
1584    }
1585
1586    private static DateTimeFormatter dayOfYearElement() {
1587        if (dye == null) {
1588            dye = new DateTimeFormatterBuilder()
1589                .appendLiteral('-')
1590                .appendDayOfYear(3)
1591                .toFormatter();
1592        }
1593        return dye;
1594    }
1595    
1596    private static DateTimeFormatter literalTElement() {
1597        if (lte == null) {
1598            lte = new DateTimeFormatterBuilder()
1599                .appendLiteral('T')
1600                .toFormatter();
1601        }
1602        return lte;
1603    }
1604
1605    private static DateTimeFormatter hourElement() {
1606        if (hde == null) {
1607            hde = new DateTimeFormatterBuilder()
1608                .appendHourOfDay(2)
1609                .toFormatter();
1610        }
1611        return hde;
1612    }
1613
1614    private static DateTimeFormatter minuteElement() {
1615        if (mhe == null) {
1616            mhe = new DateTimeFormatterBuilder()
1617                .appendLiteral(':')
1618                .appendMinuteOfHour(2)
1619                .toFormatter();
1620        }
1621        return mhe;
1622    }
1623
1624    private static DateTimeFormatter secondElement() {
1625        if (sme == null) {
1626            sme = new DateTimeFormatterBuilder()
1627                .appendLiteral(':')
1628                .appendSecondOfMinute(2)
1629                .toFormatter();
1630        }
1631        return sme;
1632    }
1633
1634    private static DateTimeFormatter millisElement() {
1635        if (lse == null) {
1636            lse = new DateTimeFormatterBuilder()
1637                .appendLiteral('.')
1638                .appendMillisOfSecond(3)
1639                .toFormatter();
1640        }
1641        return lse;
1642    }
1643
1644    private static DateTimeFormatter fractionElement() {
1645        if (fse == null) {
1646            fse = new DateTimeFormatterBuilder()
1647                .appendLiteral('.')
1648                // Support parsing up to nanosecond precision even though
1649
// those extra digits will be dropped.
1650
.appendFractionOfSecond(3, 9)
1651                .toFormatter();
1652        }
1653        return fse;
1654    }
1655
1656    private static DateTimeFormatter offsetElement() {
1657        if (ze == null) {
1658            ze = new DateTimeFormatterBuilder()
1659                .appendTimeZoneOffset("Z", true, 2, 4)
1660                .toFormatter();
1661        }
1662        return ze;
1663    }
1664
1665}
1666
Popular Tags