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 */
017
018package org.apache.commons.lang3.time;
019
020import java.util.Calendar;
021import java.util.Locale;
022import java.util.Locale.Category;
023import java.util.Map;
024import java.util.Objects;
025
026/**
027 * Helps use {@link Calendar}s.
028 *
029 * @since 3.10
030 */
031public class CalendarUtils {
032
033    /**
034     * The singleton instance for {@link Calendar#getInstance()}. The instance is created when the class is initialized and is based on the current time in the
035     * default time zone with the default {@link Category#FORMAT} locale.
036     *
037     * @see CalendarUtils#getInstance()
038     */
039    public static final CalendarUtils INSTANCE = getInstance();
040
041    /**
042     * Creates a new instance based on the current time in the default time zone with the default {@link Category#FORMAT} locale.
043     *
044     * @return a new instance.
045     * @since 3.14.0
046     */
047    public static CalendarUtils getInstance() {
048        return new CalendarUtils(Calendar.getInstance());
049    }
050
051    /**
052     * Gets a CalendarUtils using the default time zone and specified locale. The <code>CalendarUtils</code> returned is based on the current time in the
053     * default time zone with the given locale.
054     *
055     * @param locale the locale for the week data
056     * @return a Calendar.
057     */
058    static CalendarUtils getInstance(final Locale locale) {
059        return new CalendarUtils(Calendar.getInstance(locale), locale);
060    }
061
062    private final Calendar calendar;
063
064    private final Locale locale;
065
066    /**
067     * Creates an instance for the given Calendar.
068     *
069     * @param calendar A Calendar.
070     */
071    public CalendarUtils(final Calendar calendar) {
072        this(calendar, Locale.getDefault());
073    }
074
075    /**
076     * Creates an instance for the given Calendar.
077     *
078     * @param calendar A Calendar.
079     * @param locale A Locale.
080     */
081    CalendarUtils(final Calendar calendar, final Locale locale) {
082        this.calendar = Objects.requireNonNull(calendar, "calendar");
083        this.locale = Objects.requireNonNull(locale, "locale");
084    }
085    /**
086     * Gets the current day of month.
087     *
088     * @return the current day of month.
089     */
090    public int getDayOfMonth() {
091        return calendar.get(Calendar.DAY_OF_MONTH);
092    }
093
094    /**
095     * Gets the current day of year.
096     *
097     * @return the current day of year.
098     * @since 3.13.0
099     */
100    public int getDayOfYear() {
101        return calendar.get(Calendar.DAY_OF_YEAR);
102    }
103
104    /**
105     * Gets the current month.
106     *
107     * @return the current month.
108     */
109    public int getMonth() {
110        return calendar.get(Calendar.MONTH);
111    }
112
113    /**
114     * Gets month names in the requested style.
115     * @param style Must be a valid {@link Calendar#getDisplayNames(int, int, Locale)} month style.
116     * @return Styled names of months
117     */
118    String[] getMonthDisplayNames(final int style) {
119        // Unfortunately standalone month names are not available in DateFormatSymbols,
120        // so we have to extract them.
121        final Map<String, Integer> displayNames = calendar.getDisplayNames(Calendar.MONTH, style, locale);
122        if (displayNames == null) {
123            return null;
124        }
125        final String[] monthNames = new String[displayNames.size()];
126        displayNames.forEach((k, v) -> monthNames[v] = k);
127        return monthNames;
128    }
129
130    /**
131     * Gets full standalone month names as used in "LLLL" date formatting.
132     * @return Long names of months
133     */
134    String[] getStandaloneLongMonthNames() {
135        return getMonthDisplayNames(Calendar.LONG_STANDALONE);
136    }
137
138    /**
139     * Gets short standalone month names as used in "LLLL" date formatting.
140     * @return Short names of months
141     */
142    String[] getStandaloneShortMonthNames() {
143        return getMonthDisplayNames(Calendar.SHORT_STANDALONE);
144    }
145
146    /**
147     * Gets the current year.
148     *
149     * @return the current year.
150     */
151    public int getYear() {
152        return calendar.get(Calendar.YEAR);
153    }
154}