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      * Creates an instance for the given Calendar.
118      *
119      * @param calendar A Calendar.
120      * @param locale A Locale.
121      */
122     CalendarUtils(final Calendar calendar, final Locale locale) {
123         this.calendar = Objects.requireNonNull(calendar, "calendar");
124         this.locale = Objects.requireNonNull(locale, "locale");
125     }
126 
127     /**
128      * Gets the current day of month.
129      *
130      * @return the current day of month.
131      */
132     public int getDayOfMonth() {
133         return calendar.get(Calendar.DAY_OF_MONTH);
134     }
135 
136     /**
137      * Gets the current day of year.
138      *
139      * @return the current day of year.
140      * @since 3.13.0
141      */
142     public int getDayOfYear() {
143         return calendar.get(Calendar.DAY_OF_YEAR);
144     }
145 
146     /**
147      * Gets the current month.
148      *
149      * @return the current month.
150      */
151     public int getMonth() {
152         return calendar.get(Calendar.MONTH);
153     }
154 
155     /**
156      * Gets month names in the requested style.
157      * @param style Must be a valid {@link Calendar#getDisplayNames(int, int, Locale)} month style.
158      * @return Styled names of months
159      */
160     String[] getMonthDisplayNames(final int style) {
161         // Unfortunately standalone month names are not available in DateFormatSymbols,
162         // so we have to extract them.
163         final Map<String, Integer> displayNames = calendar.getDisplayNames(Calendar.MONTH, style, locale);
164         if (displayNames == null) {
165             return null;
166         }
167         final String[] monthNames = new String[displayNames.size()];
168         displayNames.forEach((k, v) -> monthNames[v] = k);
169         return monthNames;
170     }
171 
172     /**
173      * Gets full standalone month names as used in "LLLL" date formatting.
174      * @return Long names of months
175      */
176     String[] getStandaloneLongMonthNames() {
177         return getMonthDisplayNames(Calendar.LONG_STANDALONE);
178     }
179 
180     /**
181      * Gets short standalone month names as used in "LLLL" date formatting.
182      * @return Short names of months
183      */
184     String[] getStandaloneShortMonthNames() {
185         return getMonthDisplayNames(Calendar.SHORT_STANDALONE);
186     }
187 
188     /**
189      * Gets the current year.
190      *
191      * @return the current year.
192      */
193     public int getYear() {
194         return calendar.get(Calendar.YEAR);
195     }
196 
197     /**
198      * Converts this instance to a {@link LocalDate}.
199      *
200      * @return a LocalDate.
201      * @since 3.18.0
202      */
203     public LocalDate toLocalDate() {
204         return toLocalDateTime().toLocalDate();
205     }
206 
207     /**
208      * Converts this instance to a {@link LocalDateTime}.
209      *
210      * @return a LocalDateTime.
211      * @since 3.17.0
212      */
213     public LocalDateTime toLocalDateTime() {
214         return toLocalDateTime(calendar);
215     }
216 
217     /**
218      * Converts this instance to a {@link OffsetDateTime}.
219      *
220      * @return a OffsetDateTime.
221      * @since 3.17.0
222      */
223     public OffsetDateTime toOffsetDateTime() {
224         return toOffsetDateTime(calendar);
225     }
226 
227     /**
228      * Converts this instance to a {@link ZonedDateTime}.
229      *
230      * @return a ZonedDateTime.
231      * @since 3.17.0
232      */
233     public ZonedDateTime toZonedDateTime() {
234         return toZonedDateTime(calendar);
235     }
236 
237 }