Class DateTimeFormatterBuilder


  • public final class DateTimeFormatterBuilder
    extends Object
    Builder to create formatters for calendricals.

    All date-time formatters are created ultimately using this builder. Each consists of two halves a printer and a parser. Most of the methods will create both a printer and a parser automatically, however it is possible to create a formatter that only prints or only parses.

    The basic elements of calendricals can all be added:

    • Value - a numeric value
    • Fraction - a fractional value including the decimal place. Always use this when outputting fractions to ensure that the fraction is parsed correctly
    • Text - the textual equivalent for the value
    • OffsetId/Offset - the zone offset
    • ZoneId - the time-zone id
    • ZoneText - the name of the time-zone
    • Literal - a text literal
    • Nested and Optional - formats can be nested or made optional
    • Other - the printer and parser interfaces can be used to add user supplied formatting
    In addition, any of the elements may be decorated by padding, either with spaces or any other character.

    Finally, a shorthand pattern, mostly compatible with SimpleDateFormat can be used, see appendPattern(String). In practice, this simply parses the pattern and calls other methods on the builder.

    Author:
    Stephen Colebourne
    • Constructor Detail

      • DateTimeFormatterBuilder

        public DateTimeFormatterBuilder()
        Constructs a new instance of the builder.
    • Method Detail

      • parseCaseSensitive

        public DateTimeFormatterBuilder parseCaseSensitive()
        Changes the parse style to be case sensitive for the remainder of the formatter.

        Parsing can be case sensitive or insensitive - by default it is case sensitive. This controls how text is compared.

        When used, this method changes the parsing to be case sensitive from this point onwards. As case sensitive is the default, this is normally only needed after calling parseCaseInsensitive(). The change will remain in force until the end of the formatter that is eventually constructed or until parseCaseInsensitive is called.

        Returns:
        this, for chaining, never null
      • parseCaseInsensitive

        public DateTimeFormatterBuilder parseCaseInsensitive()
        Changes the parse style to be case insensitive for the remainder of the formatter.

        Parsing can be case sensitive or insensitive - by default it is case sensitive. This controls how text is compared.

        When used, this method changes the parsing to be case insensitive from this point onwards. The change will remain in force until the end of the formatter that is eventually constructed or until parseCaseSensitive is called.

        Returns:
        this, for chaining, never null
      • parseStrict

        public DateTimeFormatterBuilder parseStrict()
        Changes the parse style to be strict for the remainder of the formatter.

        Parsing can be strict or lenient - by default its strict. This controls the degree of flexibility in matching the text and sign styles.

        When used, this method changes the parsing to be strict from this point onwards. As strict is the default, this is normally only needed after calling parseLenient(). The change will remain in force until the end of the formatter that is eventually constructed or until parseLenient is called.

        Returns:
        this, for chaining, never null
      • parseLenient

        public DateTimeFormatterBuilder parseLenient()
        Changes the parse style to be lenient for the remainder of the formatter. Note that case sensitivity is set separately to this method.

        Parsing can be strict or lenient - by default its strict. This controls the degree of flexibility in matching the text and sign styles.

        When used, this method changes the parsing to be strict from this point onwards. The change will remain in force until the end of the formatter that is eventually constructed or until parseStrict is called.

        Returns:
        this, for chaining, never null
      • appendValue

        public DateTimeFormatterBuilder appendValue​(DateTimeFieldRule<?> rule)
        Appends the value of a date-time field to the formatter using a normal output style.

        The value of the field will be output during a print. If the value cannot be obtained then an exception will be thrown.

        The value will be printed as per the normal print of an integer value. Only negative numbers will be signed. No padding will be added.

        The parser for a variable width value such as this normally behaves greedily, accepting as many digits as possible. This behavior can be affected by 'adjacent value parsing'. See appendValue(DateTimeFieldRule, int) for full details.

        Parameters:
        rule - the rule of the field to append, not null
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the field rule is null
      • appendValue

        public DateTimeFormatterBuilder appendValue​(DateTimeFieldRule<?> rule,
                                                    int width)
        Appends the value of a date-time field to the formatter using a fixed width, zero-padded approach.

        The value of the field will be output during a print. If the value cannot be obtained then an exception will be thrown.

        The value will be zero-padded on the left. If the size of the value means that it cannot be printed within the width then an exception is thrown. If the value of the field is negative then an exception is thrown during printing.

        This method supports a special technique of parsing known as 'adjacent value parsing'. This technique solves the problem where a variable length value is followed by one or more fixed length values. The standard parser is greedy, and thus it would normally steal the digits that are needed by the fixed width value parsers that follow the variable width one.

        No action is required to initiate 'adjacent value parsing'. When a call to appendValue with a variable width is made, the builder enters adjacent value parsing setup mode. If the immediately subsequent method call or calls on the same builder are to this method, then the parser will reserve space so that the fixed width values can be parsed.

        For example, consider builder.appendValue(yearRule).appendValue(monthRule, 2); The year is a variable width parse of between 1 and 10 digits. The month is a fixed width parse of 2 digits. Because these were appended to the same builder immediately after one another, the year parser will reserve two digits for the month to parse. Thus, the text '200906' will correctly parse to a year of 2009 and a month of 6. Without adjacent value parsing, the year would greedily parse all six digits and leave nothing for the month.

        Adjacent value parsing applies to each set of fixed width not-negative values in the parser that immediately follow any kind of variable width value. Calling any other append method will end the setup of adjacent value parsing. Thus, in the unlikely event that you need to avoid adjacent value parsing behavior, simply add the appendValue to another DateTimeFormatterBuilder and add that to this builder.

        If the four-parameter version of appendValue is called with equal minimum and maximum widths and a sign style of not-negative then it delegates to this method.

        Parameters:
        rule - the rule of the field to append, not null
        width - the width of the printed field, from 1 to 10
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the field rule is null
        IllegalArgumentException - if the width is invalid
      • appendValue

        public DateTimeFormatterBuilder appendValue​(DateTimeFieldRule<?> rule,
                                                    int minWidth,
                                                    int maxWidth,
                                                    DateTimeFormatterBuilder.SignStyle signStyle)
        Appends the value of a date-time field to the formatter providing full control over printing.

        The value of the field will be output during a print. If the value cannot be obtained then an exception will be thrown.

        This method provides full control of the numeric formatting, including zero-padding and the positive/negative sign.

        The parser for a variable width value normally behaves greedily, accepting as many digits as possible. This behavior can be affected by 'adjacent value parsing'. See appendValue(DateTimeFieldRule, int) for full details.

        Parameters:
        rule - the rule of the field to append, not null
        minWidth - the minimum field width of the printed field, from 1 to 10
        maxWidth - the maximum field width of the printed field, from 1 to 10
        signStyle - the positive/negative output style, not null
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the field rule or sign style is null
        IllegalArgumentException - if the widths are invalid
      • appendValueReduced

        public DateTimeFormatterBuilder appendValueReduced​(DateTimeFieldRule<?> rule,
                                                           int width,
                                                           int baseValue)
        Appends the reduced value of a date-time field to the formatter.

        This is typically used for printing and parsing a two digit year. The width is the printed and parsed width. The baseValue is used during parsing to determine the valid range.

        For printing, the width is used to determine the number of characters to print. The rightmost characters are output to match the width, left padding with zero.

        For parsing, exactly the number of characters specified by the width are parsed. This is incomplete information however, so the base value is used to complete the parse. The base value is the first valid value in a range of ten to the power of width.

        For example, a base value of 1980 and a width of 2 will have valid values from 1980 to 2079. During parsing, the text "12" will result in the value 2012 as that is the value within the range where the last two digits are "12".

        This is a fixed width parser operating using 'adjacent value parsing'. See appendValue(DateTimeFieldRule, int) for full details.

        Parameters:
        rule - the rule of the field to append, not null
        width - the width of the printed and parsed field, from 1 to 8
        baseValue - the base value of the range of valid values
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the field rule is null
        IllegalArgumentException - if the width or base value is invalid
      • appendFraction

        public DateTimeFormatterBuilder appendFraction​(DateTimeFieldRule<?> rule,
                                                       int minWidth,
                                                       int maxWidth)
        Appends the fractional value of a date-time field to the formatter.

        The fractional value of the field will be output including the preceeding decimal point. The preceeding value is not output. The fraction is obtained using DateTimeFieldRule.convertIntToFraction(int).

        The width of the output fraction can be controlled. Setting the minimum width to zero will cause no output to be generated. The output fraction will have the minimum width necessary between the minimum and maximum widths - trailing zeroes are omitted. No rounding occurs due to the maximum width - digits are simply dropped.

        If the value cannot be obtained then an exception will be thrown. If the value is negative an exception will be thrown. If the field does not have a fixed set of valid values then an exception will be thrown. If the field value in the calendrical to be printed is invalid it cannot be printed and an exception will be thrown.

        Parameters:
        rule - the rule of the field to append, not null
        minWidth - the minimum width of the field excluding the decimal point, from 0 to 9
        maxWidth - the maximum width of the field excluding the decimal point, from 1 to 9
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the field rule or sign style is null
        IllegalArgumentException - if the field has a variable set of valid values
        IllegalArgumentException - if the field has a non-zero minimum
        IllegalArgumentException - if the widths are invalid
      • appendText

        public DateTimeFormatterBuilder appendText​(DateTimeFieldRule<?> rule)
        Appends the text of a date-time field to the formatter using the full text style.

        The text of the field will be output during a print. If the value cannot be obtained then an exception will be thrown. If the field has no textual representation, then the numeric value will be used.

        The value will be printed as per the normal print of an integer value. Only negative numbers will be signed. No padding will be added.

        Parameters:
        rule - the rule of the field to append, not null
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the field rule is null
      • appendText

        public DateTimeFormatterBuilder appendText​(DateTimeFieldRule<?> rule,
                                                   DateTimeFormatterBuilder.TextStyle textStyle)
        Appends the text of a date-time field to the formatter.

        The text of the field will be output during a print. If the value cannot be obtained then an exception will be thrown. If the field has no textual representation, then the numeric value will be used.

        The value will be printed as per the normal print of an integer value. Only negative numbers will be signed. No padding will be added.

        Parameters:
        rule - the rule of the field to append, not null
        textStyle - the text style to use, not null
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the field rule or text style is null
      • appendOffsetId

        public DateTimeFormatterBuilder appendOffsetId()
        Appends the zone offset, such as '+01:00', to the formatter.

        The zone offset id will be output during a print. If the offset cannot be obtained then an exception will be thrown.

        The output id is minor variation to the standard ISO-8601 format. There are three formats:

        • 'Z' - for UTC (ISO-8601)
        • '±hh:mm' - if the seconds are zero (ISO-8601)
        • '±hh:mm:ss' - if the seconds are non-zero (not ISO-8601)
        Returns:
        this, for chaining, never null
      • appendOffset

        public DateTimeFormatterBuilder appendOffset​(String utcText,
                                                     boolean includeColon,
                                                     boolean allowSeconds)
        Appends the zone offset, such as '+01:00', to the formatter.

        The zone offset will be output during a print. If the offset cannot be obtained then an exception will be thrown. The output format is controlled by the specified parameters.

        The UTC text controls what text is printed when the offset is zero. Example values would be 'Z', '+00:00', 'UTC' or 'GMT'.

        The include colon parameter controls whether a colon should separate the numeric fields or not.

        The allow seconds parameter controls whether seconds may be output. If false then seconds are never output. If true then seconds are only output if non-zero.

        Parameters:
        utcText - the text to use for UTC, not null
        includeColon - whether to include a colon
        allowSeconds - whether to allow seconds
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the UTC text is null
      • appendZoneId

        public DateTimeFormatterBuilder appendZoneId()
        Appends the time-zone rule id, such as 'Europe/Paris', to the formatter.

        The time-zone id will be output during a print. If the zone cannot be obtained then an exception will be thrown.

        Returns:
        this, for chaining, never null
      • appendZoneText

        public DateTimeFormatterBuilder appendZoneText​(DateTimeFormatterBuilder.TextStyle textStyle)
        Appends the time-zone rule name, such as 'British Summer Time', to the formatter.

        The time-zone name will be output during a print. If the zone cannot be obtained then an exception will be thrown.

        The zone name is obtained from the formatting symbols. Different names may be output depending on whether daylight savings time applies.

        If the date, time or offset cannot be obtained it may not be possible to determine which text to output. In this case, the text representing time without daylight savings (winter time) will be used.

        Parameters:
        textStyle - the text style to use, not null
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the text style is null
      • appendLocalized

        public DateTimeFormatterBuilder appendLocalized​(DateTimeFormatterBuilder.FormatStyle dateStyle,
                                                        DateTimeFormatterBuilder.FormatStyle timeStyle)
        Appends a localized date-time pattern to the formatter.

        The pattern is resolved lazily using the locale being used during the print/parse (stored in DateTimeFormatter.

        The pattern can vary by chronology, although typically it doesn't. This method uses the standard ISO chronology patterns.

        Parameters:
        dateStyle - the date style to use, null means no date required
        timeStyle - the time style to use, null means no time required
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the text style is null
      • appendLocalized

        public DateTimeFormatterBuilder appendLocalized​(DateTimeFormatterBuilder.FormatStyle dateStyle,
                                                        DateTimeFormatterBuilder.FormatStyle timeStyle,
                                                        Chronology chronology)
        Appends a localized date-time pattern to the formatter.

        The pattern is resolved lazily using the locale being used during the print/parse (stored in DateTimeFormatter.

        The pattern can vary by chronology, although typically it doesn't. This method allows the chronology to be specified.

        Parameters:
        dateStyle - the date style to use, null means no date required
        timeStyle - the time style to use, null means no time required
        chronology - the chronology to use, not null
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the text style is null
      • appendLiteral

        public DateTimeFormatterBuilder appendLiteral​(char literal)
        Appends a character literal to the formatter.

        This character will be output during a print.

        Parameters:
        literal - the literal to append, not null
        Returns:
        this, for chaining, never null
      • appendLiteral

        public DateTimeFormatterBuilder appendLiteral​(String literal)
        Appends a string literal to the formatter.

        This string will be output during a print.

        If the literal is empty, nothing is added to the formatter.

        Parameters:
        literal - the literal to append, not null
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the literal is null
      • append

        public DateTimeFormatterBuilder append​(DateTimePrinter printer,
                                               DateTimeParser parser)
        Appends a printer and/or parser to the formatter.

        If one of the two parameters is null then the formatter will only be able to print or parse. If both are null, an exception is thrown.

        Parameters:
        printer - the printer to add, null prevents the formatter from printing
        parser - the parser to add, null prevents the formatter from parsing
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if both printer and parser are null
      • append

        public DateTimeFormatterBuilder append​(DateTimeFormatter formatter)
        Appends all the elements of a formatter to the builder.

        This method has the same effect as appending each of the constituent parts of the formatter directly to this builder.

        Parameters:
        formatter - the formatter to add, not null
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the formatter is null
      • appendOptional

        public DateTimeFormatterBuilder appendOptional​(DateTimeFormatter formatter)
        Appends a formatter to the builder which will optionally print/parse.

        This method has the same effect as appending each of the constituent parts directly to this builder surrounded by an optionalStart() and optionalEnd().

        The formatter will print if data is available for all the fields contained within it. The formatter will parse if the string matches, otherwise no error is returned.

        Parameters:
        formatter - the formatter to add, not null
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the formatter is null
      • appendPattern

        public DateTimeFormatterBuilder appendPattern​(String pattern)
        Appends the elements defined by the specified pattern to the builder.

        All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. The following pattern letters are defined:

          Symbol  Meaning                     Presentation      Examples
          ------  -------                     ------------      -------
           y       year                        year              2004; 04
           D       day-of-year                 number            189
           M       month-of-year               month             July; Jul; 07
           d       day-of-month                number            10
        
           Q       quarter-of-year             number            3
           q       month-of-quarter            number            2
        
           x       week-based-year             year              1996
           w       week-of-week-based-year     number            27
           e       day-of-week                 number            2
           E       day-of-week                 text              Tuesday; Tue
           F       week-of-month               number            3
        
           a       am-pm-of-day                text              PM
           h       clock-hour-of-am-pm (1-12)  number            12
           K       hour-of-am-pm (0-11)        number/fraction   0
           k       clock-hour-of-am-pm (1-24)  number            0
        
           H       hour-of-day (0-23)          number/fraction   0
           m       minute-of-hour              number/fraction   30
           s       second-of-minute            number/fraction   55
           S       milli-of-second             number/fraction   978
           n       nano-of-second              number/fraction   987654321
        
           I       time-zone ID                zoneID            America/Los_Angeles
           z       time-zone name              text              Pacific Standard Time; PST
           Z       zone-offset                 offset            -0800; -08:00;
        
           f       make next a fraction        fraction modifier .123
           p       pad next                    pad modifier      1
        
           '       escape for text             delimiter
           ''      single quote                literal           '
           [       optional section start
           ]       optional section end
         

        The count of pattern letters determine the format.

        Text: If the number of pattern letters is 4 or more, the full textual form is used as per DateTimeFormatterBuilder.TextStyle.FULL. Otherwise a short form is used, as per DateTimeFormatterBuilder.TextStyle.SHORT.

        Number: If the count of letters is one, then the value is printed using the minimum number of digits and without padding as per appendValue(DateTimeFieldRule). Otherwise, the count of digits is used as the width of the output field as per appendValue(DateTimeFieldRule, int).

        Fraction modifier: Modifies the pattern that immediately follows to be a fraction. All fractional values must use the 'f' prefix to ensure correct parsing. The fraction also outputs the decimal point. If the count of 'f' is one, then the fractional value has the exact number of digits defined by the count of the value being output. If the count of 'f' is two or more, then the fractional value has the a minimum number of digits defined by the count of the value being output and a maximum output of nine digits.

        For example, 'ssffnnn' outputs the second followed by 3-9 digits of the nanosecond, while 'mmfss' outputs the minute followed by exactly 2 digits representing the second.

        Year: The count of letters determines the minimum field width below which padding is used. If the count of letters is two, then a reduced two digit form is used. For printing, this outputs the rightmost two digits. For parsing, this will parse using the base value of 2000, resulting in a year within the range 2000 to 2099 inclusive. If the count of letters is less than four (but not two), then the sign is only output for negative years as per DateTimeFormatterBuilder.SignStyle.NORMAL. Otherwise, the sign is output if the pad width is exceeded, as per DateTimeFormatterBuilder.SignStyle.EXCEEDS_PAD

        Month: If the count of letters is 3 or greater, use the Text rules above. Otherwise use the Number rules above.

        ZoneID: 'I' outputs the zone id, such as 'Europe/Paris'.

        Offset: 'Z' outputs offset without a colon, without seconds and '+0000' as the text for UTC. 'ZZ' outputs the offset with a colon, without seconds and '+00:00' as the text for UTC. 'ZZZ' outputs offset without a colon, with seconds and 'Z' as the text for UTC (ISO-8601 style). 'ZZZZ' outputs the offset with a colon, with seconds and 'Z' as the text for UTC (ISO-8601 style).

        Zone names: Time zone names ('z') cannot be parsed.

        Optional section: The optional section markers work exactly like calling optionalStart() and optionalEnd().

        Pad modifier: Modifies the pattern that immediately follows to be padded with spaces. The pad width is determined by the number of pattern letters. This is the same as calling padNext(int).

        For example, 'ppH' outputs the hour-of-day padded on the left with spaces to a width of 2.

        Any unrecognized letter will be output directly. However, since these are reserved, that may change in future versions. Any non-letter character, other than '[', ']' and the single quote will be output directly. Despite this, it is recommended to use single quotes around all characters that you want to output directly to ensure that future changes do not break your application.

        The pattern string is similar, but not identical, to SimpleDateFormat. SimpleDateFormat pattern letters 'G' and 'W' are not available. Pattern letters 'x', 'Q', 'q', 'e', 'n', 'I', 'f' and 'p' are added. Letters 'y', 'z' and 'Z' have some differences.

        Parameters:
        pattern - the pattern to add, not null
        Returns:
        this, for chaining, never null
        Throws:
        NullPointerException - if the pattern is null
        IllegalArgumentException - if the pattern is invalid
      • padNext

        public DateTimeFormatterBuilder padNext​(int padWidth)
        Causes the next added printer/parser to pad to a fixed width using a space.

        This padding will pad to a fixed width using spaces.

        An exception will be thrown during printing if the pad width is exceeded.

        Parameters:
        padWidth - the pad width, 1 or greater
        Returns:
        this, for chaining, never null
        Throws:
        IllegalArgumentException - if pad width is too small
      • padNext

        public DateTimeFormatterBuilder padNext​(int padWidth,
                                                char padChar)
        Causes the next added printer/parser to pad to a fixed width.

        This padding is intended for padding other than zero-padding. Zero-padding should be achieved using the appendValue methods.

        An exception will be thrown during printing if the pad width is exceeded.

        Parameters:
        padWidth - the pad width, 1 or greater
        padChar - the pad character
        Returns:
        this, for chaining, never null
        Throws:
        IllegalArgumentException - if pad width is too small
      • optionalStart

        public DateTimeFormatterBuilder optionalStart()
        Mark the start of an optional section.

        The output of printing can include optional sections, which may be nested. An optional section is started by calling this method and ended by calling optionalEnd() or by ending the build process.

        All elements in the optional section are treated as optional. During printing, the section is only output if data is available in the Calendrical for all the elements in the section. During parsing, the whole section may be missing from the parsed string.

        For example, consider a builder setup as builder.appendValue(hourRule,2).optionalStart().appendValue(minuteRule,2). The optional section ends automatically at the end of the builder. During printing, the minute will only be output if its value can be obtained from the calendrical. During parsing, the input will be successfully parsed whether the minute is present or not.

        Returns:
        this, for chaining, never null
      • optionalEnd

        public DateTimeFormatterBuilder optionalEnd()
        Ends an optional section.

        The output of printing can include optional sections, which may be nested. An optional section is started by calling optionalStart() and ended using this method (or at the end of the builder).

        Calling this method without having previously called optionalStart will throw an exception. Calling this method immediately after calling optionalStart has no effect on the formatter other than ending the (empty) optional section.

        All elements in the optional section are treated as optional. During printing, the section is only output if data is available in the Calendrical for all the elements in the section. During parsing, the whole section may be missing from the parsed string.

        For example, consider a builder setup as builder.appendValue(hourRule,2).optionalStart().appendValue(minuteRule,2).optionalEnd(). During printing, the minute will only be output if its value can be obtained from the calendrical. During parsing, the input will be successfully parsed whether the minute is present or not.

        Returns:
        this, for chaining, never null
        Throws:
        IllegalStateException - if there was no previous call to optionalStart
      • toFormatter

        public DateTimeFormatter toFormatter()
        Completes this builder by creating the DateTimeFormatter using the default locale.

        Calling this method will end any open optional sections by repeatedly calling optionalEnd() before creating the formatter.

        This builder can still be used after creating the formatter if desired, although the state may have been changed by calls to optionalEnd.

        Returns:
        the created formatter, never null
      • toFormatter

        public DateTimeFormatter toFormatter​(Locale locale)
        Completes this builder by creating the DateTimeFormatter using the specified locale.

        Calling this method will end any open optional sections by repeatedly calling optionalEnd() before creating the formatter.

        This builder can still be used after creating the formatter if desired, although the state may have been changed by calls to optionalEnd.

        Parameters:
        locale - the locale to use for formatting, not null
        Returns:
        the created formatter, never null