001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.commons.utils;
018
019import static org.apache.juneau.commons.utils.StringUtils.*;
020import static org.apache.juneau.commons.utils.ThrowableUtils.*;
021
022import java.time.format.*;
023
024import org.apache.juneau.commons.collections.*;
025
026/**
027 * A utility class for parsing and formatting HTTP dates as used in cookies and other headers.
028 *
029 * <p>
030 * This class handles dates as defined by RFC 2616 section 3.3.1 as well as some other common non-standard formats.
031 *
032 * <p>
033 * This class was copied from HttpClient 4.3.
034 *
035 */
036public class DateUtils {
037
038   /**
039    * Prevents instantiation.
040    */
041   private DateUtils() {}
042
043   private static final Cache<String,DateTimeFormatter> DATE_TIME_FORMATTER_CACHE = Cache.of(String.class, DateTimeFormatter.class)
044      .maxSize(100)
045      .supplier(pattern -> {
046         if (isEmpty(pattern))
047            return DateTimeFormatter.ISO_INSTANT;
048         try {
049            for (var f : DateTimeFormatter.class.getFields()) {
050               if (f.getName().equals(pattern)) {
051                  return (DateTimeFormatter)f.get(null);
052               }
053            }
054            return DateTimeFormatter.ofPattern(pattern);
055         } catch (IllegalArgumentException | IllegalAccessException e) {
056            throw toRuntimeException(e);
057         }
058      })
059      .build();
060
061   /**
062    * Returns a {@link DateTimeFormatter} using either a pattern or predefined pattern name.
063    *
064    * @param pattern The pattern (e.g. <js>"yyyy-MM-dd"</js>) or pattern name (e.g. <js>"ISO_INSTANT"</js>).  Can be <jk>null</jk> or empty, in which case {@link DateTimeFormatter#ISO_INSTANT} is returned.
065    * @return The formatter.
066    */
067   public static DateTimeFormatter getDateTimeFormatter(String pattern) {
068      return DATE_TIME_FORMATTER_CACHE.get(pattern);
069   }
070}