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 * https://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.time.LocalDate; 021import java.time.LocalDateTime; 022import java.time.OffsetDateTime; 023import java.time.ZoneId; 024import java.time.ZonedDateTime; 025import java.util.Calendar; 026import java.util.Locale; 027import java.util.Locale.Category; 028import java.util.Map; 029import java.util.Objects; 030 031/** 032 * Helps use {@link Calendar}s. 033 * 034 * @since 3.10 035 */ 036public class CalendarUtils { 037 038 /** 039 * 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 040 * default time zone with the default {@link Category#FORMAT} locale. 041 * 042 * @see CalendarUtils#getInstance() 043 */ 044 public static final CalendarUtils INSTANCE = getInstance(); 045 046 /** 047 * Creates a new instance based on the current time in the default time zone with the default {@link Category#FORMAT} locale. 048 * 049 * @return a new instance. 050 * @since 3.14.0 051 */ 052 public static CalendarUtils getInstance() { 053 return new CalendarUtils(Calendar.getInstance()); 054 } 055 056 /** 057 * Gets a CalendarUtils using the default time zone and specified locale. The {@code CalendarUtils} returned is based on the current time in the 058 * default time zone with the given locale. 059 * 060 * @param locale the locale for the week data 061 * @return a Calendar. 062 */ 063 static CalendarUtils getInstance(final Locale locale) { 064 return new CalendarUtils(Calendar.getInstance(locale), locale); 065 } 066 067 /** 068 * Converts a Calendar to a LocalDateTime. 069 * 070 * @param calendar the Calendar to convert. 071 * @return a LocalDateTime. 072 * @since 3.17.0 073 */ 074 public static LocalDateTime toLocalDateTime(final Calendar calendar) { 075 return LocalDateTime.ofInstant(calendar.toInstant(), toZoneId(calendar)); 076 } 077 078 /** 079 * Converts a Calendar to a OffsetDateTime. 080 * 081 * @param calendar the Calendar to convert. 082 * @return a OffsetDateTime. 083 * @since 3.17.0 084 */ 085 public static OffsetDateTime toOffsetDateTime(final Calendar calendar) { 086 return OffsetDateTime.ofInstant(calendar.toInstant(), toZoneId(calendar)); 087 } 088 089 /** 090 * Converts a Calendar to a ZonedDateTime. 091 * 092 * @param calendar the Calendar to convert. 093 * @return a ZonedDateTime. 094 * @since 3.17.0 095 */ 096 public static ZonedDateTime toZonedDateTime(final Calendar calendar) { 097 return ZonedDateTime.ofInstant(calendar.toInstant(), toZoneId(calendar)); 098 } 099 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}