View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.lang3.time;
19  
20  import java.time.LocalDate;
21  import java.time.LocalDateTime;
22  import java.time.OffsetDateTime;
23  import java.time.ZoneId;
24  import java.time.ZonedDateTime;
25  import java.util.Calendar;
26  import java.util.Locale;
27  import java.util.Locale.Category;
28  import java.util.Map;
29  import java.util.Objects;
30  
31  /**
32   * Helps use {@link Calendar}s.
33   *
34   * @since 3.10
35   */
36  public class CalendarUtils {
37  
38      /**
39       * 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
40       * default time zone with the default {@link Category#FORMAT} locale.
41       *
42       * @see CalendarUtils#getInstance()
43       */
44      public static final CalendarUtils INSTANCE = getInstance();
45  
46      /**
47       * Creates a new instance based on the current time in the default time zone with the default {@link Category#FORMAT} locale.
48       *
49       * @return a new instance.
50       * @since 3.14.0
51       */
52      public static CalendarUtils getInstance() {
53          return new CalendarUtils(Calendar.getInstance());
54      }
55  
56      /**
57       * Gets a CalendarUtils using the default time zone and specified locale. The {@code CalendarUtils} returned is based on the current time in the
58       * default time zone with the given locale.
59       *
60       * @param locale the locale for the week data
61       * @return a Calendar.
62       */
63      static CalendarUtils getInstance(final Locale locale) {
64          return new CalendarUtils(Calendar.getInstance(locale), locale);
65      }
66  
67      /**
68       * Converts a Calendar to a LocalDateTime.
69       *
70       * @param calendar the Calendar to convert.
71       * @return a LocalDateTime.
72       * @since 3.17.0
73       */
74      public static LocalDateTime toLocalDateTime(final Calendar calendar) {
75          return LocalDateTime.ofInstant(calendar.toInstant(), toZoneId(calendar));
76      }
77  
78      /**
79       * Converts a Calendar to a OffsetDateTime.
80       *
81       * @param calendar the Calendar to convert.
82       * @return a OffsetDateTime.
83       * @since 3.17.0
84       */
85      public static OffsetDateTime toOffsetDateTime(final Calendar calendar) {
86          return OffsetDateTime.ofInstant(calendar.toInstant(), toZoneId(calendar));
87      }
88  
89      /**
90       * Converts a Calendar to a ZonedDateTime.
91       *
92       * @param calendar the Calendar to convert.
93       * @return a ZonedDateTime.
94       * @since 3.17.0
95       */
96      public static ZonedDateTime toZonedDateTime(final Calendar calendar) {
97          return ZonedDateTime.ofInstant(calendar.toInstant(), toZoneId(calendar));
98      }
99  
100     private static ZoneId toZoneId(final Calendar calendar) {
101         return calendar.getTimeZone().toZoneId();
102     }
103 
104     private final Calendar calendar;
105 
106     private final Locale locale;
107 
108     /**
109      * Creates an instance for the given Calendar.
110      *
111      * @param calendar A Calendar.
112      */
113     public CalendarUtils(final Calendar calendar) {
114         this(calendar, Locale.getDefault());
115     }
116 
117     /**
118      * Creates an instance for the given Calendar.
119      *
120      * @param calendar A Calendar.
121      * @param locale A Locale.
122      */
123     CalendarUtils(final Calendar calendar, final Locale locale) {
124         this.calendar = Objects.requireNonNull(calendar, "calendar");
125         this.locale = Objects.requireNonNull(locale, "locale");
126     }
127 
128     /**
129      * Gets the current day of month.
130      *
131      * @return the current day of month.
132      */
133     public int getDayOfMonth() {
134         return calendar.get(Calendar.DAY_OF_MONTH);
135     }
136 
137     /**
138      * Gets the current day of year.
139      *
140      * @return the current day of year.
141      * @since 3.13.0
142      */
143     public int getDayOfYear() {
144         return calendar.get(Calendar.DAY_OF_YEAR);
145     }
146 
147     /**
148      * Gets the current month.
149      *
150      * @return the current month.
151      */
152     public int getMonth() {
153         return calendar.get(Calendar.MONTH);
154     }
155 
156     /**
157      * Gets month names in the requested style.
158      *
159      * @param style Must be a valid {@link Calendar#getDisplayNames(int, int, Locale)} month style.
160      * @return Styled names of months
161      */
162     String[] getMonthDisplayNames(final int style) {
163         // Unfortunately standalone month names are not available in DateFormatSymbols,
164         // so we have to extract them.
165         final Map<String, Integer> displayNames = calendar.getDisplayNames(Calendar.MONTH, style, locale);
166         if (displayNames == null) {
167             return null;
168         }
169         final String[] monthNames = new String[displayNames.size()];
170         displayNames.forEach((k, v) -> monthNames[v] = k);
171         return monthNames;
172     }
173 
174     /**
175      * Gets full standalone month names as used in "LLLL" date formatting.
176      *
177      * @return Long names of months
178      */
179     String[] getStandaloneLongMonthNames() {
180         return getMonthDisplayNames(Calendar.LONG_STANDALONE);
181     }
182 
183     /**
184      * Gets short standalone month names as used in "LLLL" date formatting.
185      *
186      * @return Short names of months
187      */
188     String[] getStandaloneShortMonthNames() {
189         return getMonthDisplayNames(Calendar.SHORT_STANDALONE);
190     }
191 
192     /**
193      * Gets the current year.
194      *
195      * @return the current year.
196      */
197     public int getYear() {
198         return calendar.get(Calendar.YEAR);
199     }
200 
201     /**
202      * Converts this instance to a {@link LocalDate}.
203      *
204      * @return a LocalDate.
205      * @since 3.18.0
206      */
207     public LocalDate toLocalDate() {
208         return toLocalDateTime().toLocalDate();
209     }
210 
211     /**
212      * Converts this instance to a {@link LocalDateTime}.
213      *
214      * @return a LocalDateTime.
215      * @since 3.17.0
216      */
217     public LocalDateTime toLocalDateTime() {
218         return toLocalDateTime(calendar);
219     }
220 
221     /**
222      * Converts this instance to a {@link OffsetDateTime}.
223      *
224      * @return a OffsetDateTime.
225      * @since 3.17.0
226      */
227     public OffsetDateTime toOffsetDateTime() {
228         return toOffsetDateTime(calendar);
229     }
230 
231     /**
232      * Converts this instance to a {@link ZonedDateTime}.
233      *
234      * @return a ZonedDateTime.
235      * @since 3.17.0
236      */
237     public ZonedDateTime toZonedDateTime() {
238         return toZonedDateTime(calendar);
239     }
240 
241 }