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 * 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 LocalDateTime. 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}