All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.phloc.web.datetime.PDTWebDateUtils Maven / Gradle / Ivy

/**
 * Copyright (C) 2006-2015 phloc systems
 * http://www.phloc.com
 * office[at]phloc[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.phloc.web.datetime;

import java.util.Locale;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import org.joda.time.Chronology;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.joda.time.chrono.ISOChronology;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;

import com.phloc.commons.annotations.PresentForCodeCoverage;
import com.phloc.commons.collections.pair.IReadonlyPair;
import com.phloc.commons.collections.pair.ReadonlyPair;
import com.phloc.datetime.PDTFactory;
import com.phloc.datetime.config.PDTConfig;
import com.phloc.datetime.format.PDTFormatter;
import com.phloc.datetime.format.PDTFromString;

/**
 * A helper class that parses Dates out of Strings with date time in RFC822 and
 * W3CDateTime formats plus the variants Atom (0.3) and RSS (0.9, 0.91, 0.92,
 * 0.93, 0.94, 1.0 and 2.0) specificators added to those formats.
 * 

* It uses the JDK java.text.SimpleDateFormat class attempting the parse using a * mask for each one of the possible formats. *

* Original work Copyright 2004 Sun Microsystems, Inc. * * @author Alejandro Abdelnur (original; mainly the formatting masks) * @author Philip Helger (major modification) */ @Immutable public final class PDTWebDateUtils { private static final String FORMAT_RFC822 = "EEE, dd MMM yyyy HH:mm:ss 'GMT'"; private static final String FORMAT_W3C = "yyyy-MM-dd'T'HH:mm:ss'Z'"; /* * order is like this because the SimpleDateFormat.parse does not fail with * exception if it can parse a valid date out of a substring of the full * string given the mask so we have to check the most complete format first, * then it fails with exception */ private static final String [] RFC822_MASKS = { "EEE, dd MMM yy HH:mm:ss", "EEE, dd MMM yy HH:mm", "dd MMM yy HH:mm:ss", "dd MMM yy HH:mm" }; /* * order is like this because the SimpleDateFormat.parse does not fail with * exception if it can parse a valid date out of a substring of the full * string given the mask so we have to check the most complete format first, * then it fails with exception */ private static final String [] W3CDATETIME_MASKS = { "yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd't'HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "yyyy-MM-dd't'HH:mm:ss.SSS'z'", "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd't'HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd't'HH:mm:ss", FORMAT_W3C, "yyyy-MM-dd't'HH:mm:ss'z'", "yyyy-MM-dd'T'HH:mm", /* * Applies to the * following 2: together * with logic in the * parseW3CDateTime they * handle W3C dates * without time forcing * them to be GMT */ "yyyy-MM'T'HH:mm", "yyyy'T'HH:mm", "yyyy-MM-dd't'HH:mm", "yyyy-MM-dd'T'HH:mm'Z'", "yyyy-MM-dd't'HH:mm'z'", "yyyy-MM-dd", "yyyy-MM", "yyyy" }; private static final Locale LOCALE_TO_USE = Locale.US; @PresentForCodeCoverage @SuppressWarnings ("unused") private static final PDTWebDateUtils s_aInstance = new PDTWebDateUtils (); private PDTWebDateUtils () {} /** * Parses a Date out of a string using an array of masks. *

* It uses the masks in order until one of them succeeds or all fail. *

* * @param aMasks * array of masks to use for parsing the string * @param sDate * string to parse for a date. * @param aDTZ * The date/time zone to use. Optional. * @return the Date represented by the given string using one of the given * masks. It returns null if it was not possible to parse the * the string with any of the masks. */ @Nullable private static DateTime _parseDateTimeUsingMask (@Nonnull final String [] aMasks, @Nonnull final String sDate, @Nullable final DateTimeZone aDTZ) { for (final String sMask : aMasks) { DateTimeFormatter aDTF = PDTFormatter.getForPattern (sMask, LOCALE_TO_USE) .withChronology (PDTConfig.getDefaultChronology ()); if (aDTZ != null) aDTF = aDTF.withZone (aDTZ); final DateTime aDT = PDTFromString.getDateTimeFromString (sDate, aDTF); if (aDT != null) return aDT; } return null; } @Nullable private static LocalDateTime _parseLocalDateTimeUsingMask (@Nonnull final String [] aMasks, @Nonnull final String sDate, @Nullable final DateTimeZone aDTZ) { for (final String sMask : aMasks) { DateTimeFormatter aDTF = PDTFormatter.getForPattern (sMask, LOCALE_TO_USE) .withChronology (PDTConfig.getDefaultChronology ()); if (aDTZ != null) aDTF = aDTF.withZone (aDTZ); final LocalDateTime aDT = PDTFromString.getLocalDateTimeFromString (sDate, aDTF); if (aDT != null) return aDT; } return null; } /** * Extract the time zone from the passed string. UTC and GMT are supported. * * @param sDate * The date string. * @return A non-null pair, where the first element is the * remaining string to be parsed (never null) and the * second element is the extracted time zone (may be null * ). */ @Nonnull private static IReadonlyPair _extractDateTimeZone (@Nonnull final String sDate) { final String [] aDTZ = { "UTC", "GMT" }; for (final String sDTZ : aDTZ) { if (sDate.endsWith (" " + sDTZ)) return ReadonlyPair.create (sDate.substring (0, sDate.length () - (1 + sDTZ.length ())), DateTimeZone.forID (sDTZ)); if (sDate.endsWith (sDTZ)) return ReadonlyPair.create (sDate.substring (0, sDate.length () - sDTZ.length ()), DateTimeZone.forID (sDTZ)); } return ReadonlyPair.create (sDate, null); } /** * Parses a Date out of a String with a date in RFC822 format. *

* It parsers the following formats: *

    *
  • "EEE, dd MMM yyyy HH:mm:ss z"
  • *
  • "EEE, dd MMM yyyy HH:mm z"
  • *
  • "EEE, dd MMM yy HH:mm:ss z"
  • *
  • "EEE, dd MMM yy HH:mm z"
  • *
  • "dd MMM yyyy HH:mm:ss z"
  • *
  • "dd MMM yyyy HH:mm z"
  • *
  • "dd MMM yy HH:mm:ss z"
  • *
  • "dd MMM yy HH:mm z"
  • *
*

* Refer to the java.text.SimpleDateFormat javadocs for details on the format * of each element. *

* * @param sDate * string to parse for a date. May be null. * @return the Date represented by the given RFC822 string. It returns * null if it was not possible to parse the given string into a * {@link DateTime} or if the passed {@link String} was * null. */ @Nullable public static DateTime getDateTimeFromRFC822 (@Nullable final String sDate) { if (sDate == null) return null; final IReadonlyPair aPair = _extractDateTimeZone (sDate.trim ()); return _parseDateTimeUsingMask (RFC822_MASKS, aPair.getFirst (), aPair.getSecond ()); } /** * Parses a Date out of a String with a date in RFC822 format. *

* It parsers the following formats: *

    *
  • "EEE, dd MMM yyyy HH:mm:ss z"
  • *
  • "EEE, dd MMM yyyy HH:mm z"
  • *
  • "EEE, dd MMM yy HH:mm:ss z"
  • *
  • "EEE, dd MMM yy HH:mm z"
  • *
  • "dd MMM yyyy HH:mm:ss z"
  • *
  • "dd MMM yyyy HH:mm z"
  • *
  • "dd MMM yy HH:mm:ss z"
  • *
  • "dd MMM yy HH:mm z"
  • *
*

* Refer to the java.text.SimpleDateFormat javadocs for details on the format * of each element. *

* * @param sDate * string to parse for a date. May be null. * @return the Date represented by the given RFC822 string. It returns * null if it was not possible to parse the given string into a * {@link DateTime} or if the passed {@link String} was * null. */ @Nullable public static LocalDateTime getLocalDateTimeFromRFC822 (@Nullable final String sDate) { if (sDate == null) return null; final IReadonlyPair aPair = _extractDateTimeZone (sDate.trim ()); return _parseLocalDateTimeUsingMask (RFC822_MASKS, aPair.getFirst (), aPair.getSecond ()); } /** * Parses a Date out of a String with a date in W3C date-time format. *

* It parsers the following formats: *

    *
  • "yyyy-MM-dd'T'HH:mm:ssz"
  • *
  • "yyyy-MM-dd'T'HH:mmz"
  • *
  • "yyyy-MM-dd"
  • *
  • "yyyy-MM"
  • *
  • "yyyy"
  • *
*

* Refer to the java.text.SimpleDateFormat javadocs for details on the format * of each element. *

* * @param sDate * string to parse for a date. May be null. * @return the Date represented by the given W3C date-time string. It returns * null if it was not possible to parse the given string into a * {@link DateTime} or if the input string was null. */ @Nullable public static DateTime getDateTimeFromW3C (@Nullable final String sDate) { if (sDate == null) return null; final IReadonlyPair aPair = _extractDateTimeZone (sDate.trim ()); return _parseDateTimeUsingMask (W3CDATETIME_MASKS, aPair.getFirst (), aPair.getSecond ()); } /** * Parses a Date out of a String with a date in W3C date-time format. *

* It parsers the following formats: *

    *
  • "yyyy-MM-dd'T'HH:mm:ssz"
  • *
  • "yyyy-MM-dd'T'HH:mmz"
  • *
  • "yyyy-MM-dd"
  • *
  • "yyyy-MM"
  • *
  • "yyyy"
  • *
*

* Refer to the java.text.SimpleDateFormat javadocs for details on the format * of each element. *

* * @param sDate * string to parse for a date. May be null. * @return the Date represented by the given W3C date-time string. It returns * null if it was not possible to parse the given string into a * {@link DateTime} or if the input string was null. */ @Nullable public static LocalDateTime getLocalDateTimeFromW3C (@Nullable final String sDate) { if (sDate == null) return null; final IReadonlyPair aPair = _extractDateTimeZone (sDate.trim ()); return _parseLocalDateTimeUsingMask (W3CDATETIME_MASKS, aPair.getFirst (), aPair.getSecond ()); } /** * Parses a Date out of a String with a date in W3C date-time format or in a * RFC822 format. *

* * @param sDate * string to parse for a date. * @return the Date represented by the given W3C date-time string. It returns * null if it was not possible to parse the given string into a * Date. */ @Nullable public static DateTime getDateTimeFromW3COrRFC822 (@Nullable final String sDate) { DateTime aDateTime = getDateTimeFromW3C (sDate); if (aDateTime == null) aDateTime = getDateTimeFromRFC822 (sDate); return aDateTime; } /** * Parses a Date out of a String with a date in W3C date-time format or in a * RFC822 format. *

* * @param sDate * string to parse for a date. * @return the Date represented by the given W3C date-time string. It returns * null if it was not possible to parse the given string into a * Date. */ @Nullable public static LocalDateTime getLocalDateTimeFromW3COrRFC822 (@Nullable final String sDate) { LocalDateTime aDateTime = getLocalDateTimeFromW3C (sDate); if (aDateTime == null) aDateTime = getLocalDateTimeFromRFC822 (sDate); return aDateTime; } /** * create a RFC822 representation of a date. * * @param aDateTime * Date to parse. If null the current date and time is * used. * @return the RFC822 represented by the given Date. */ @Nonnull public static String getAsStringRFC822 (@Nullable final DateTime aDateTime) { return PDTFormatter.getForPattern (FORMAT_RFC822, LOCALE_TO_USE) .withZone (PDTConfig.getDateTimeZoneUTC ()) .print (aDateTime); } /** * create a RFC822 representation of a date time using UTC date time zone. * * @param aDateTime * Date to parse. If null the current date and time is * used. * @return the RFC822 represented by the given Date. */ @Nonnull public static String getAsStringRFC822 (@Nullable final LocalDateTime aDateTime) { return PDTFormatter.getForPattern (FORMAT_RFC822, LOCALE_TO_USE) .withZone (PDTConfig.getDateTimeZoneUTC ()) .print (aDateTime); } /** * create a W3C Date Time representation of a date. * * @param aDateTime * Date to parse. If null the current date and time is * used. * @return the W3C Date Time represented by the given Date. */ @Nonnull public static String getAsStringW3C (@Nullable final DateTime aDateTime) { DateTimeFormatter aFormatter = PDTFormatter.getForPattern (FORMAT_W3C, LOCALE_TO_USE); if (aDateTime != null) aFormatter = aFormatter.withZone (aDateTime.getZone ()); return aFormatter.print (aDateTime); } /** * create a W3C Date Time representation of a date time using UTC date time * zone. * * @param aDateTime * Date to parse. If null the current date and time is * used. * @return the W3C Date Time represented by the given Date. */ @Nonnull public static String getAsStringW3C (@Nullable final LocalDateTime aDateTime) { return getAsStringW3C (aDateTime == null ? (DateTime) null : aDateTime.toDateTime (PDTConfig.getDateTimeZoneUTC ())); } /** * @return The current date time formatted using RFC 822 */ @Nonnull public static String getCurrentDateTimeAsStringRFC822 () { // Important to use date time zone GMT as this is what the standard // printer emits! // Use no milli seconds as the standard printer does not print them! final DateTime aNow = PDTFactory.getCurrentDateTime ().withZone (DateTimeZone.forID ("GMT")).withMillisOfSecond (0); return getAsStringRFC822 (aNow); } /** * @return The current date time formatted using W3C format */ @Nonnull public static String getCurrentDateTimeAsStringW3C () { // Use no milli seconds as the standard printer does not print them! final DateTime aNow = PDTFactory.getCurrentDateTime ().withMillisOfSecond (0); return getAsStringW3C (aNow); } @Nonnull private static DateTimeFormatter _getXSDFormatterDateTime (@Nonnull final Chronology aChronology) { return ISODateTimeFormat.dateTime ().withChronology (aChronology); } @Nullable public static DateTime getDateTimeFromXSD (@Nullable final String sValue) { return getDateTimeFromXSD (sValue, ISOChronology.getInstanceUTC ()); } @Nullable public static DateTime getDateTimeFromXSD (@Nullable final String sValue, @Nonnull final Chronology aChronology) { return PDTFromString.getDateTimeFromString (sValue, _getXSDFormatterDateTime (aChronology)); } @Nullable public static LocalDateTime getLocalDateTimeFromXSD (@Nullable final String sValue) { // For LocalDateTime always use the default chronology return PDTFromString.getLocalDateTimeFromString (sValue, _getXSDFormatterDateTime (PDTConfig.getDefaultChronology ())); } @Nonnull public static String getAsStringXSD (@Nullable final DateTime aDateTime) { return getAsStringXSD (ISOChronology.getInstanceUTC (), aDateTime); } @Nonnull public static String getAsStringXSD (@Nonnull final Chronology aChronology, @Nullable final DateTime aDateTime) { return _getXSDFormatterDateTime (aChronology).print (aDateTime); } @Nonnull public static String getAsStringXSD (@Nullable final LocalDateTime aLocalDateTime) { // For LocalDateTime always use the default chronology return _getXSDFormatterDateTime (PDTConfig.getDefaultChronology ()).print (aLocalDateTime); } @Nonnull private static DateTimeFormatter _getXSDFormatterDate () { return ISODateTimeFormat.date ().withChronology (ISOChronology.getInstanceUTC ()); } @Nullable public static LocalDate getLocalDateFromXSD (@Nullable final String sValue) { final DateTime aDT = PDTFromString.getDateTimeFromString (sValue, _getXSDFormatterDate ()); return aDT == null ? null : aDT.withChronology (PDTConfig.getDefaultChronologyUTC ()).toLocalDate (); } @Nonnull public static String getAsStringXSD (@Nullable final LocalDate aLocalDate) { return _getXSDFormatterDate ().print (aLocalDate == null ? PDTFactory.getCurrentLocalDate () : aLocalDate); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy