001/*
002 * Copyright 2002-2013 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.util.StringUtils;
028
029/**
030 * Factory that creates a Joda-Time {@link DateTimeFormatter}.
031 *
032 * <p>Formatters will be created using the defined {@link #setPattern pattern},
033 * {@link #setIso ISO}, and {@link #setStyle style} methods (considered in that order).
034 *
035 * @author Phillip Webb
036 * @author Sam Brannen
037 * @since 3.2
038 * @see #createDateTimeFormatter()
039 * @see #createDateTimeFormatter(DateTimeFormatter)
040 * @see #setPattern
041 * @see #setStyle
042 * @see #setIso
043 * @see DateTimeFormatterFactoryBean
044 */
045public class DateTimeFormatterFactory {
046
047        private String pattern;
048
049        private ISO iso;
050
051        private String style;
052
053        private TimeZone timeZone;
054
055
056        /**
057         * Create a new {@code DateTimeFormatterFactory} instance.
058         */
059        public DateTimeFormatterFactory() {
060        }
061
062        /**
063         * Create a new {@code DateTimeFormatterFactory} instance.
064         * @param pattern the pattern to use to format date values
065         */
066        public DateTimeFormatterFactory(String pattern) {
067                this.pattern = pattern;
068        }
069
070
071        /**
072         * Set the pattern to use to format date values.
073         * @param pattern the format pattern
074         */
075        public void setPattern(String pattern) {
076                this.pattern = pattern;
077        }
078
079        /**
080         * Set the ISO format used to format date values.
081         * @param iso the ISO format
082         */
083        public void setIso(ISO iso) {
084                this.iso = iso;
085        }
086
087        /**
088         * Set the two characters to use to format date values, in Joda-Time style.
089         * <p>The first character is used for the date style; the second is for
090         * the time style. Supported characters are:
091         * <ul>
092         * <li>'S' = Small</li>
093         * <li>'M' = Medium</li>
094         * <li>'L' = Long</li>
095         * <li>'F' = Full</li>
096         * <li>'-' = Omitted</li>
097         * </ul>
098         * @param style two characters from the set {"S", "M", "L", "F", "-"}
099         */
100        public void setStyle(String style) {
101                this.style = style;
102        }
103
104        /**
105         * Set the {@code TimeZone} to normalize the date values into, if any.
106         * @param timeZone the time zone
107         */
108        public void setTimeZone(TimeZone timeZone) {
109                this.timeZone = timeZone;
110        }
111
112
113        /**
114         * Create a new {@code DateTimeFormatter} using this factory.
115         * <p>If no specific pattern or style has been defined,
116         * {@link DateTimeFormat#mediumDateTime() medium date time format} will be used.
117         * @return a new date time formatter
118         * @see #createDateTimeFormatter(DateTimeFormatter)
119         */
120        public DateTimeFormatter createDateTimeFormatter() {
121                return createDateTimeFormatter(DateTimeFormat.mediumDateTime());
122        }
123
124        /**
125         * Create a new {@code DateTimeFormatter} using this factory.
126         * <p>If no specific pattern or style has been defined,
127         * the supplied {@code fallbackFormatter} will be used.
128         * @param fallbackFormatter the fall-back formatter to use when no specific
129         * factory properties have been set (can be {@code null}).
130         * @return a new date time formatter
131         */
132        public DateTimeFormatter createDateTimeFormatter(DateTimeFormatter fallbackFormatter) {
133                DateTimeFormatter dateTimeFormatter = null;
134                if (StringUtils.hasLength(this.pattern)) {
135                        dateTimeFormatter = DateTimeFormat.forPattern(this.pattern);
136                }
137                else if (this.iso != null && this.iso != ISO.NONE) {
138                        switch (this.iso) {
139                                case DATE:
140                                        dateTimeFormatter = ISODateTimeFormat.date();
141                                        break;
142                                case TIME:
143                                        dateTimeFormatter = ISODateTimeFormat.time();
144                                        break;
145                                case DATE_TIME:
146                                        dateTimeFormatter = ISODateTimeFormat.dateTime();
147                                        break;
148                                case NONE:
149                                        /* no-op */
150                                        break;
151                                default:
152                                        throw new IllegalStateException("Unsupported ISO format: " + this.iso);
153                        }
154                }
155                else if (StringUtils.hasLength(this.style)) {
156                        dateTimeFormatter = DateTimeFormat.forStyle(this.style);
157                }
158
159                if (dateTimeFormatter != null && this.timeZone != null) {
160                        dateTimeFormatter = dateTimeFormatter.withZone(DateTimeZone.forTimeZone(this.timeZone));
161                }
162                return (dateTimeFormatter != null ? dateTimeFormatter : fallbackFormatter);
163        }
164
165}