/** * Copyright (C) 2014-2020 Philip Helger (www.helger.com) * philip[at]helger[dot]com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.helger.commons.datetime; import java.sql.Timestamp; import java.time.Clock; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; import java.time.MonthDay; import java.time.OffsetDateTime; import java.time.Year; import java.time.YearMonth; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; import java.util.TimeZone; import javax.annotation.Nonnegative; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import javax.xml.datatype.XMLGregorianCalendar; import com.helger.commons.CGlobal; @Immutable public final class PDTFactory { private PDTFactory () {} @Nonnull private static ZoneId _getZoneId () { return PDTConfig.getDefaultZoneId (); } /** * Get the time zone offset to UTC of the passed Date in minutes to be used in * {@link XMLGregorianCalendar}. * * @param aDate * The date to use. May not be <code>null</code>. * @return 0 for no offset to UTC, the minutes otherwise. Usually in 60minutes * steps :) */ @SuppressWarnings ("deprecation") public static int getTimezoneOffsetInMinutes (@Nonnull final Date aDate) { return -aDate.getTimezoneOffset (); } public static int getTimezoneOffsetInMinutes (@Nonnull final GregorianCalendar aCal) { final long nOffsetMillis = aCal.getTimeZone ().getRawOffset (); return Math.toIntExact (nOffsetMillis / CGlobal.MILLISECONDS_PER_MINUTE); } public static int getTimezoneOffsetInMinutes (@Nonnull final ZoneId aZID, @Nonnull final Instant aAt) { final ZoneOffset aZO = aZID.getRules ().getStandardOffset (aAt); return getTimezoneOffsetInMinutes (aZO); } public static int getTimezoneOffsetInMinutes (@Nonnull final ZoneOffset aZO) { return aZO.getTotalSeconds () / CGlobal.SECONDS_PER_MINUTE; } @Nonnull public static ZoneOffset getZoneOffsetFromOffsetInMinutes (final int nOffsetInMinutes) { return ZoneOffset.ofHoursMinutes (nOffsetInMinutes / CGlobal.MINUTES_PER_HOUR, nOffsetInMinutes % CGlobal.MINUTES_PER_HOUR); } @Nonnull public static ZoneId getZoneIdFromOffsetInMinutes (final int nOffsetInMinutes) { final ZoneOffset aZO = getZoneOffsetFromOffsetInMinutes (nOffsetInMinutes); // Empty prefix means "no special" return ZoneId.ofOffset ("", aZO); } @Nonnull public static TimeZone getTimeZone (@Nonnull final Date aDate) { final int nOffsetMin = getTimezoneOffsetInMinutes (aDate); final ZoneId aZI = getZoneIdFromOffsetInMinutes (nOffsetMin); return TimeZone.getTimeZone (aZI); } // To ZonedDateTime @Nonnull public static ZonedDateTime getCurrentZonedDateTime () { return ZonedDateTime.now (_getZoneId ()); } /** * Get the passed date time but with micro and nanoseconds set to 0, so that * only the milliseconds part is present. This is helpful for XSD * serialization, where only milliseconds granularity is available. * * @param aODT * Source date time. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>, the local * date time with microseconds and nanoseconds set to 0 otherwise. * @since 9.2.0 */ @Nullable public static ZonedDateTime getWithMillisOnly (@Nullable final ZonedDateTime aODT) { return aODT == null ? null : aODT.withNano (aODT.get (ChronoField.MILLI_OF_SECOND) * (int) CGlobal.NANOSECONDS_PER_MILLISECOND); } /** * @return The current local date and time but with micro and nanoseconds set * to 0, so that only the milliseconds part is present. This is * helpful for XSD serialization, where only milliseconds granularity * is available. * @since 9.2.0 */ @Nonnegative public static ZonedDateTime getCurrentZonedDateTimeMillisOnly () { return getWithMillisOnly (getCurrentZonedDateTime ()); } @Nonnull public static ZonedDateTime getCurrentZonedDateTimeUTC () { return ZonedDateTime.now (ZoneOffset.UTC); } /** * @return The current local date and time but with micro and nanoseconds set * to 0, so that only the milliseconds part is present. This is * helpful for XSD serialization, where only milliseconds granularity * is available. * @since 9.2.0 */ @Nonnegative public static ZonedDateTime getCurrentZonedDateTimeUTCMillisOnly () { return getWithMillisOnly (getCurrentZonedDateTimeUTC ()); } @Nullable public static ZonedDateTime createZonedDateTime (@Nullable final OffsetDateTime aODT) { return aODT == null ? null : aODT.toZonedDateTime (); } @Nullable public static ZonedDateTime createZonedDateTime (@Nullable final LocalDateTime aLDT) { return aLDT == null ? null : ZonedDateTime.of (aLDT, _getZoneId ()); } @Nullable public static ZonedDateTime createZonedDateTime (@Nullable final LocalDate aLD) { return createZonedDateTime (createLocalDateTime (aLD)); } @Nullable public static ZonedDateTime createZonedDateTime (@Nullable final YearMonth aYM) { return createZonedDateTime (createLocalDateTime (aYM)); } @Nullable public static ZonedDateTime createZonedDateTime (@Nullable final Year aYear) { return createZonedDateTime (createLocalDateTime (aYear)); } @Nullable public static ZonedDateTime createZonedDateTime (@Nullable final LocalTime aLT) { return createZonedDateTime (createLocalDateTime (aLT)); } @Nonnull public static ZonedDateTime createZonedDateTime (final int nYear, final Month eMonth, final int nDay) { return createZonedDateTime (createLocalDateTime (nYear, eMonth, nDay)); } @Nonnull public static ZonedDateTime createZonedDateTime (final int nYear, @Nonnull final Month eMonth, final int nDay, final int nHour, final int nMinute, final int nSecond) { return createZonedDateTime (createLocalDateTime (nYear, eMonth, nDay, nHour, nMinute, nSecond)); } @Nullable public static ZonedDateTime createZonedDateTime (@Nullable final Instant aInstant) { return aInstant == null ? null : ZonedDateTime.ofInstant (aInstant, _getZoneId ()); } @Nullable public static ZonedDateTime createZonedDateTime (@Nullable final GregorianCalendar aCal) { return aCal == null ? null : aCal.toZonedDateTime (); } @Nullable public static ZonedDateTime createZonedDateTime (@Nullable final Date aDate) { return createZonedDateTime (createLocalDateTime (aDate)); } @Nullable public static ZonedDateTime createZonedDateTime (@Nullable final Timestamp aTimestamp) { return createZonedDateTime (createLocalDateTime (aTimestamp)); } @Nonnull public static ZonedDateTime createZonedDateTime (final long nMillis) { return createZonedDateTime (createLocalDateTime (nMillis)); } @Nonnull public static ZonedDateTime createZonedDateTime (@Nullable final Number aMillis) { return createZonedDateTime (createLocalDateTime (aMillis)); } // To OffsetDateTime @Nonnegative public static OffsetDateTime getCurrentOffsetDateTime () { return OffsetDateTime.now (_getZoneId ()); } /** * Get the passed date time but with micro and nanoseconds set to 0, so that * only the milliseconds part is present. This is helpful for XSD * serialization, where only milliseconds granularity is available. * * @param aODT * Source date time. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>, the local * date time with microseconds and nanoseconds set to 0 otherwise. * @since 9.2.0 */ @Nullable public static OffsetDateTime getWithMillisOnly (@Nullable final OffsetDateTime aODT) { return aODT == null ? null : aODT.withNano (aODT.get (ChronoField.MILLI_OF_SECOND) * (int) CGlobal.NANOSECONDS_PER_MILLISECOND); } /** * @return The current local date and time but with micro and nanoseconds set * to 0, so that only the milliseconds part is present. This is * helpful for XSD serialization, where only milliseconds granularity * is available. * @since 9.2.0 */ @Nonnegative public static OffsetDateTime getCurrentOffsetDateTimeMillisOnly () { return getWithMillisOnly (getCurrentOffsetDateTime ()); } @Nullable public static OffsetDateTime createOffsetDateTime (@Nullable final ZonedDateTime aZDT) { return aZDT == null ? null : aZDT.toOffsetDateTime (); } @Nullable public static OffsetDateTime createOffsetDateTime (@Nullable final LocalDateTime aLDT) { return createOffsetDateTime (createZonedDateTime (aLDT)); } @Nullable public static OffsetDateTime createOffsetDateTime (@Nullable final LocalDate aLD) { return createOffsetDateTime (createZonedDateTime (aLD)); } @Nullable public static OffsetDateTime createOffsetDateTime (@Nullable final YearMonth aYM) { return createOffsetDateTime (createZonedDateTime (aYM)); } @Nullable public static OffsetDateTime createOffsetDateTime (@Nullable final Year aYear) { return createOffsetDateTime (createZonedDateTime (aYear)); } @Nullable public static OffsetDateTime createOffsetDateTime (@Nullable final LocalTime aLT) { return createOffsetDateTime (createZonedDateTime (aLT)); } @Nonnull public static OffsetDateTime createOffsetDateTime (final int nYear, final Month eMonth, final int nDay) { return createOffsetDateTime (createZonedDateTime (nYear, eMonth, nDay)); } @Nonnull public static OffsetDateTime createOffsetDateTime (final int nYear, @Nonnull final Month eMonth, final int nDay, final int nHour, final int nMinute, final int nSecond) { return createOffsetDateTime (createZonedDateTime (nYear, eMonth, nDay, nHour, nMinute, nSecond)); } @Nullable public static OffsetDateTime createOffsetDateTime (@Nullable final Instant aInstant) { return aInstant == null ? null : OffsetDateTime.ofInstant (aInstant, _getZoneId ()); } @Nullable public static OffsetDateTime createOffsetDateTime (@Nullable final Date aDate) { return createOffsetDateTime (createLocalDateTime (aDate)); } @Nullable public static OffsetDateTime createOffsetDateTime (@Nullable final Timestamp aTimestamp) { return createOffsetDateTime (createLocalDateTime (aTimestamp)); } @Nullable public static OffsetDateTime createOffsetDateTime (@Nullable final GregorianCalendar aCal) { return createOffsetDateTime (aCal == null ? null : aCal.toZonedDateTime ()); } @Nonnull public static OffsetDateTime createOffsetDateTime (final long nMillis) { return createOffsetDateTime (createLocalDateTime (nMillis)); } @Nullable public static OffsetDateTime createOffsetDateTime (@Nullable final Number aMillis) { return createOffsetDateTime (createLocalDateTime (aMillis)); } // To LocalDateTime @Nonnegative public static LocalDateTime getCurrentLocalDateTime () { return LocalDateTime.now (_getZoneId ()); } /** * Get the passed date time but with micro and nanoseconds set to 0, so that * only the milliseconds part is present. This is helpful for XSD * serialization, where only milliseconds granularity is available. * * @param aLDT * Source date time. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>, the local * date time with microseconds and nanoseconds set to 0 otherwise. * @since 9.2.0 */ @Nullable public static LocalDateTime getWithMillisOnly (@Nullable final LocalDateTime aLDT) { return aLDT == null ? null : aLDT.withNano (aLDT.get (ChronoField.MILLI_OF_SECOND) * (int) CGlobal.NANOSECONDS_PER_MILLISECOND); } /** * @return The current local date and time but with micro and nanoseconds set * to 0, so that only the milliseconds part is present. This is * helpful for XSD serialization, where only milliseconds granularity * is available. * @since 9.2.0 */ @Nonnegative public static LocalDateTime getCurrentLocalDateTimeMillisOnly () { return getWithMillisOnly (getCurrentLocalDateTime ()); } @Nullable public static LocalDateTime createLocalDateTime (@Nullable final ZonedDateTime aDT) { return aDT == null ? null : aDT.toLocalDateTime (); } @Nullable public static LocalDateTime createLocalDateTime (@Nullable final OffsetDateTime aDT) { return aDT == null ? null : aDT.toLocalDateTime (); } @Nullable public static LocalDateTime createLocalDateTime (@Nullable final LocalDate aLD) { return aLD == null ? null : aLD.atStartOfDay (); } @Nullable public static LocalDateTime createLocalDateTime (@Nullable final YearMonth aYM) { return createLocalDateTime (createLocalDate (aYM)); } @Nullable public static LocalDateTime createLocalDateTime (@Nullable final Year aYear) { return createLocalDateTime (createLocalDate (aYear)); } @Nullable public static LocalDateTime createLocalDateTime (@Nullable final LocalTime aLT) { return aLT == null ? null : aLT.atDate (LocalDate.ofEpochDay (0)); } @Nonnull public static LocalDateTime createLocalDateTime (final int nYear, @Nonnull final Month eMonth, final int nDay) { return createLocalDateTime (nYear, eMonth, nDay, 0, 0, 0); } @Nonnull public static LocalDateTime createLocalDateTime (final int nYear, @Nonnull final Month eMonth, final int nDay, final int nHour, final int nMinute) { return createLocalDateTime (nYear, eMonth, nDay, nHour, nMinute, 0); } @Nonnull public static LocalDateTime createLocalDateTime (final int nYear, @Nonnull final Month eMonth, final int nDay, final int nHour, final int nMinute, final int nSecond) { return LocalDateTime.of (nYear, eMonth, nDay, nHour, nMinute, nSecond); } @Nullable public static LocalDateTime createLocalDateTime (@Nullable final Instant aInstant) { return aInstant == null ? null : LocalDateTime.ofInstant (aInstant, _getZoneId ()); } @Nullable public static LocalDateTime createLocalDateTime (@Nullable final Date aDate) { return aDate == null ? null : createLocalDateTime (aDate.toInstant ()); } @Nullable public static LocalDateTime createLocalDateTime (@Nullable final Timestamp aDate) { return aDate == null ? null : aDate.toLocalDateTime (); } @Nullable public static LocalDateTime createLocalDateTime (@Nullable final GregorianCalendar aCal) { return aCal == null ? null : createLocalDateTime (aCal.toZonedDateTime ()); } @Nonnull public static LocalDateTime createLocalDateTime (final long nMillis) { return createLocalDateTime (Instant.ofEpochMilli (nMillis)); } @Nullable public static LocalDateTime createLocalDateTime (@Nullable final Number aMillis) { return aMillis == null ? null : createLocalDateTime (aMillis.longValue ()); } // To LocalDate @Nonnegative public static LocalDate getCurrentLocalDate () { return LocalDate.now (_getZoneId ()); } @Nonnull public static LocalDate createLocalDate (final int nYear, @Nonnull final Month eMonth, final int nDayOfMonth) { return LocalDate.of (nYear, eMonth, nDayOfMonth); } @Nullable public static LocalDate createLocalDate (@Nullable final GregorianCalendar aCalendar) { return aCalendar == null ? null : aCalendar.toZonedDateTime ().toLocalDate (); } @Nonnull public static LocalDate createLocalDate (final long nMillis) { return createLocalDateTime (nMillis).toLocalDate (); } @Nullable public static LocalDate createLocalDate (@Nullable final Instant aInstant) { return aInstant == null ? null : createLocalDateTime (aInstant).toLocalDate (); } @Nullable public static LocalDate createLocalDate (@Nullable final Date aDate) { return aDate == null ? null : createLocalDate (aDate.toInstant ()); } @Nullable public static LocalDate createLocalDate (@Nullable final YearMonth aYM) { return aYM == null ? null : aYM.atDay (1); } @Nullable public static LocalDate createLocalDate (@Nullable final Year aYear) { return aYear == null ? null : aYear.atDay (1); } @Nullable public static LocalDate createLocalDate (@Nullable final LocalDateTime aLDT) { return aLDT == null ? null : aLDT.toLocalDate (); } // To LocalTime @Nonnegative public static LocalTime getCurrentLocalTime () { return LocalTime.now (_getZoneId ()); } @Nullable public static LocalTime createLocalTime (@Nullable final GregorianCalendar aCalendar) { return aCalendar == null ? null : aCalendar.toZonedDateTime ().toLocalTime (); } @Nonnull public static LocalTime createLocalTime (final long nMillis) { return createLocalDateTime (nMillis).toLocalTime (); } @Nullable public static LocalTime createLocalTime (@Nullable final Instant aInstant) { return aInstant == null ? null : createLocalDateTime (aInstant).toLocalTime (); } @Nullable public static LocalTime createLocalTime (@Nullable final Date aDate) { return aDate == null ? null : createLocalTime (aDate.toInstant ()); } @Nullable public static LocalTime createLocalTime (@Nullable final LocalDateTime aLDT) { return aLDT == null ? null : aLDT.toLocalTime (); } @Nonnull public static LocalTime createLocalTime (final int nHour, final int nMinute, final int nSecond) { return LocalTime.of (nHour, nMinute, nSecond); } // To Date @Nullable public static Date createDate (@Nullable final ZonedDateTime aZDT) { // The timezone gets lost here return aZDT == null ? null : Date.from (aZDT.toInstant ()); } @Nullable public static Date createDate (@Nullable final OffsetDateTime aODT) { // The timezone gets lost here return aODT == null ? null : Date.from (aODT.toInstant ()); } @Nullable public static Date createDate (@Nullable final LocalDateTime aLDT) { return createDate (createZonedDateTime (aLDT)); } @Nullable public static Date createDate (@Nullable final LocalDate aLD) { return createDate (createZonedDateTime (aLD)); } @Nullable public static Date createDate (@Nullable final LocalTime aLT) { return createDate (createZonedDateTime (aLT)); } @Nonnull public static Date createDateForDate (final int nYear, @Nonnull final Month eMonth, final int nDayOfMonth) { return createDate (createLocalDate (nYear, eMonth, nDayOfMonth)); } @Nonnull public static Date createDateForTime (final int nHour, final int nMin, final int nSec) { return createDate (createLocalTime (nHour, nMin, nSec)); } @Nonnull public static Calendar createCalendar () { return Calendar.getInstance (PDTConfig.getDefaultTimeZone (), Locale.getDefault (Locale.Category.FORMAT)); } @Nonnull public static Calendar createCalendarUTC () { return Calendar.getInstance (PDTConfig.getUTCTimeZone (), Locale.getDefault (Locale.Category.FORMAT)); } @Nonnull public static GregorianCalendar createGregorianCalendar () { return new GregorianCalendar (PDTConfig.getDefaultTimeZone (), Locale.getDefault (Locale.Category.FORMAT)); } @Nonnull public static GregorianCalendar createGregorianCalendarUTC () { return new GregorianCalendar (PDTConfig.getUTCTimeZone (), Locale.getDefault (Locale.Category.FORMAT)); } // Misc @Nonnegative public static int getCurrentYear () { return getCurrentLocalDate ().getYear (); } @Nonnull public static Year getCurrentYearObj () { return Year.now (_getZoneId ()); } @Nonnegative public static int getCurrentMonth () { return getCurrentLocalDate ().getMonthValue (); } @Nonnull public static Month getCurrentMonthObj () { return getCurrentLocalDate ().getMonth (); } @Nonnegative public static int getCurrentDayOfMonth () { return getCurrentLocalDate ().getDayOfMonth (); } @Nonnull public static MonthDay getCurrentMonthDay () { return MonthDay.now (_getZoneId ()); } @Nonnegative public static YearMonth getCurrentYearMonth () { return YearMonth.now (_getZoneId ()); } @Nonnegative public static Instant getCurrentInstant () { return Instant.now (Clock.system (_getZoneId ())); } public static long getCurrentMillis () { return getCurrentInstant ().toEpochMilli (); } public static long getMillis (@Nonnull final LocalDate aLD) { return createZonedDateTime (aLD).toInstant ().toEpochMilli (); } public static long getMillis (@Nonnull final LocalTime aLT) { return createZonedDateTime (aLT).toInstant ().toEpochMilli (); } public static long getMillis (@Nonnull final LocalDateTime aLDT) { return createZonedDateTime (aLDT).toInstant ().toEpochMilli (); } public static long getMillis (@Nonnull final OffsetDateTime aODT) { return aODT.toInstant ().toEpochMilli (); } public static long getMillis (@Nonnull final ZonedDateTime aZDT) { return aZDT.toInstant ().toEpochMilli (); } }