001/*
002 * Copyright 2002-2017 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.format.datetime.joda;
018
019import java.util.TimeZone;
020
021import org.joda.time.DateTimeZone;
022import org.joda.time.format.DateTimeFormat;
023import org.joda.time.format.DateTimeFormatter;
024import org.joda.time.format.ISODateTimeFormat;
025
026import org.springframework.format.annotation.DateTimeFormat.ISO;
027import org.springframework.lang.Nullable;
028import org.springframework.util.StringUtils;
029
030/**
031 * Factory that creates a Joda-Time {@link DateTimeFormatter}.
032 *
033 * <p>Formatters will be created using the defined {@link #setPattern pattern},
034 * {@link #setIso ISO}, and {@link #setStyle style} methods (considered in that order).
035 *
036 * @author Phillip Webb
037 * @author Sam Brannen
038 * @since 3.2
039 * @see #createDateTimeFormatter()
040 * @see #createDateTimeFormatter(DateTimeFormatter)
041 * @see #setPattern
042 * @see #setStyle
043 * @see #setIso
044 * @see DateTimeFormatterFactoryBean
045 */
046public class DateTimeFormatterFactory {
047
048        @Nullable
049        private String pattern;
050
051        @Nullable
052        private ISO iso;
053
054        @Nullable
055        private String style;
056
057        @Nullable
058        private TimeZone timeZone;
059
060
061        /**
062         * Create a new {@code DateTimeFormatterFactory} instance.
063         */
064        public DateTimeFormatterFactory() {
065        }
066
067        /**
068         * Create a new {@code DateTimeFormatterFactory} instance.
069         * @param pattern the pattern to use to format date values
070         */
071        public DateTimeFormatterFactory(String pattern) {
072                this.pattern = pattern;
073        }
074
075
076        /**
077         * Set the pattern to use to format date values.
078         * @param pattern the format pattern
079         */
080        public void setPattern(String pattern) {
081                this.pattern = pattern;
082        }
083
084        /**
085         * Set the ISO format used to format date values.
086         * @param iso the ISO format
087         */
088        public void setIso(ISO iso) {
089                this.iso = iso;
090        }
091
092        /**
093         * Set the two characters to use to format date values, in Joda-Time style.
094         * <p>The first character is used for the date style; the second is for
095         * the time style. Supported characters are:
096         * <ul>
097         * <li>'S' = Small</li>
098         * <li>'M' = Medium</li>
099         * <li>'L' = Long</li>
100         * <li>'F' = Full</li>
101         * <li>'-' = Omitted</li>
102         * </ul>
103         * @param style two characters from the set {"S", "M", "L", "F", "-"}
104         */
105        public void setStyle(String style) {
106                this.style = style;
107        }
108
109        /**
110         * Set the {@code TimeZone} to normalize the date values into, if any.
111         * @param timeZone the time zone
112         */
113        public void setTimeZone(TimeZone timeZone) {
114                this.timeZone = timeZone;
115        }
116
117
118        /**
119         * Create a new {@code DateTimeFormatter} using this factory.
120         * <p>If no specific pattern or style has been defined,
121         * {@link DateTimeFormat#mediumDateTime() medium date time format} will be used.
122         * @return a new date time formatter
123         * @see #createDateTimeFormatter(DateTimeFormatter)
124         */
125        public DateTimeFormatter createDateTimeFormatter() {
126                return createDateTimeFormatter(DateTimeFormat.mediumDateTime());
127        }
128
129        /**
130         * Create a new {@code DateTimeFormatter} using this factory.
131         * <p>If no specific pattern or style has been defined,
132         * the supplied {@code fallbackFormatter} will be used.
133         * @param fallbackFormatter the fall-back formatter to use
134         * when no specific factory properties have been set
135         * @return a new date time formatter
136         */
137        public DateTimeFormatter createDateTimeFormatter(DateTimeFormatter fallbackFormatter) {
138                DateTimeFormatter dateTimeFormatter = null;
139                if (StringUtils.hasLength(this.pattern)) {
140                        dateTimeFormatter = DateTimeFormat.forPattern(this.pattern);
141                }
142                else if (this.iso != null && this.iso != ISO.NONE) {
143                        switch (this.iso) {
144                                case DATE:
145                                        dateTimeFormatter = ISODateTimeFormat.date();
146                                        break;
147                                case TIME:
148                                        dateTimeFormatter = ISODateTimeFormat.time();
149                                        break;
150                                case DATE_TIME:
151                                        dateTimeFormatter = ISODateTimeFormat.dateTime();
152                                        break;
153                                default:
154                                        throw new IllegalStateException("Unsupported ISO format: " + this.iso);
155                        }
156                }
157                else if (StringUtils.hasLength(this.style)) {
158                        dateTimeFormatter = DateTimeFormat.forStyle(this.style);
159                }
160
161                if (dateTimeFormatter != null && this.timeZone != null) {
162                        dateTimeFormatter = dateTimeFormatter.withZone(DateTimeZone.forTimeZone(this.timeZone));
163                }
164                return (dateTimeFormatter != null ? dateTimeFormatter : fallbackFormatter);
165        }
166
167}