001/*
002 * Copyright 2002-2018 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.standard;
018
019import java.time.format.DateTimeFormatter;
020import java.util.Locale;
021
022import org.springframework.core.NamedThreadLocal;
023import org.springframework.lang.Nullable;
024
025/**
026 * A holder for a thread-local user {@link DateTimeContext}.
027 *
028 * @author Juergen Hoeller
029 * @since 4.0
030 * @see org.springframework.context.i18n.LocaleContextHolder
031 */
032public final class DateTimeContextHolder {
033
034        private static final ThreadLocal<DateTimeContext> dateTimeContextHolder =
035                        new NamedThreadLocal<>("DateTimeContext");
036
037
038        private DateTimeContextHolder() {
039        }
040
041
042        /**
043         * Reset the DateTimeContext for the current thread.
044         */
045        public static void resetDateTimeContext() {
046                dateTimeContextHolder.remove();
047        }
048
049        /**
050         * Associate the given DateTimeContext with the current thread.
051         * @param dateTimeContext the current DateTimeContext,
052         * or {@code null} to reset the thread-bound context
053         */
054        public static void setDateTimeContext(@Nullable DateTimeContext dateTimeContext) {
055                if (dateTimeContext == null) {
056                        resetDateTimeContext();
057                }
058                else {
059                        dateTimeContextHolder.set(dateTimeContext);
060                }
061        }
062
063        /**
064         * Return the DateTimeContext associated with the current thread, if any.
065         * @return the current DateTimeContext, or {@code null} if none
066         */
067        @Nullable
068        public static DateTimeContext getDateTimeContext() {
069                return dateTimeContextHolder.get();
070        }
071
072
073        /**
074         * Obtain a DateTimeFormatter with user-specific settings applied to the given base Formatter.
075         * @param formatter the base formatter that establishes default formatting rules
076         * (generally user independent)
077         * @param locale the current user locale (may be {@code null} if not known)
078         * @return the user-specific DateTimeFormatter
079         */
080        public static DateTimeFormatter getFormatter(DateTimeFormatter formatter, @Nullable Locale locale) {
081                DateTimeFormatter formatterToUse = (locale != null ? formatter.withLocale(locale) : formatter);
082                DateTimeContext context = getDateTimeContext();
083                return (context != null ? context.getFormatter(formatterToUse) : formatterToUse);
084        }
085
086}