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

com.huaweicloud.dis.core.util.DateUtils Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2002-2010 the original author or authors.
 *
 * 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.huaweicloud.dis.core.util;

import com.huaweicloud.dis.core.ClientException;

import org.apache.http.annotation.Contract;
import org.apache.http.annotation.ThreadingBehavior;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.joda.time.tz.FixedDateTimeZone;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

/**
 * Utilities for parsing and formatting dates.
 */
@Contract(threading = ThreadingBehavior.SAFE)
public class DateUtils {
    private static final DateTimeZone GMT = new FixedDateTimeZone("GMT", "GMT", 0, 0);
    private static final long MILLI_SECONDS_OF_365_DAYS = 365L*24*60*60*1000;

    private static final int DATE_MILLI_SECOND_PRECISION = 3;

    /** ISO 8601 format */
    protected static final DateTimeFormatter iso8601DateFormat =
        ISODateTimeFormat.dateTime().withZone(GMT);

    /** Alternate ISO 8601 format without fractional seconds */
    protected static final DateTimeFormatter alternateIso8601DateFormat =
        DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'").withZone(GMT);

    /** RFC 822 format */
    protected static final DateTimeFormatter rfc822DateFormat =
        DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss z")
                      .withLocale(Locale.US)
                      .withZone(GMT);

    /**
     * This is another ISO 8601 format that's used in clock skew error response
     */
    protected static final DateTimeFormatter compressedIso8601DateFormat =
            DateTimeFormat.forPattern("yyyyMMdd'T'HHmmss'Z'")
            .withZone(GMT);

	/**
	 * @deprecated by the more efficient static method
	 *             {@link #parseISO8601Date(String)}
	 * 
	 * @param dateString
	 *            The date string to parse.
	 * @return The parsed Date object.
	 */
    @Deprecated
    public Date parseIso8601Date(String dateString) {
        return parseISO8601Date(dateString);
    }

    /**
     * Parses the specified date string as an ISO 8601 date and returns the Date
     * object.
     *
     * @param dateString
     *            The date string to parse.
     *
     * @return The parsed Date object.
     */
    public static Date parseISO8601Date(String dateString) {
        try {
            return doParseISO8601Date(dateString);
        } catch(RuntimeException ex) {
            throw handleException(ex);
        }
    }

    static Date doParseISO8601Date(final String dateStringOrig) {
        final String temp = tempDateStringForJodaTime(dateStringOrig);
        try {
            if (temp.equals(dateStringOrig)) {
                // Normal case: nothing special here
                return new Date(iso8601DateFormat.parseMillis(dateStringOrig));
            }
            // Handling edge case:
            // Joda-time can only handle up to year 292278993 but we are given
            // 292278994;  So we parse the date string by first adjusting
            // the year to 292278993. Then we add 1 year back afterwards.
            final long milliLess365Days = iso8601DateFormat.parseMillis(temp);
            final long milli = milliLess365Days + MILLI_SECONDS_OF_365_DAYS;
            if (milli < 0) { // overflow!
                // re-parse the original date string using JodaTime so as to
                // throw  an exception with a consistent message
                return new Date(iso8601DateFormat.parseMillis(dateStringOrig));
            }
            return new Date(milli);
        } catch (IllegalArgumentException e) {
            try {
                return new Date(alternateIso8601DateFormat.parseMillis(dateStringOrig));
                // If the first ISO 8601 parser didn't work, try the alternate
                // version which doesn't include fractional seconds
            } catch(Exception oops) {
                // no the alternative route doesn't work; let's bubble up the original exception
                throw e;
            }
        }
    }

    /**
     * Returns a date string with the prefix temporarily substituted, if
     * applicable, so that JodaTime can handle it.  Otherwise, if not applicable,
     * the original date string is returned.
     */
    private static String tempDateStringForJodaTime(String dateString) {
        final String fromPrefix = "292278994-";
        final String toPrefix   = "292278993-";
        return dateString.startsWith(fromPrefix)
             ? toPrefix + dateString.substring(fromPrefix.length())
             : dateString;
    }

    /**
     * Returns the original runtime exception iff the joda-time being used
     * at runtime behaves as expected.
     *
     * @throws IllegalStateException if the joda-time being used at runtime
     * doens't appear to be of the right version.
     */
    private static  E handleException(E ex) {
        if (JodaTime.hasExpectedBehavior())
            return ex;
        throw new IllegalStateException("Joda-time 2.2 or later version is required, but found version: " + JodaTime.getVersion(), ex);
    }

	/**
	 * @deprecated by the more efficient static method
	 *             {@link #formatISO8601Date(java.util.Date)}
	 * 
	 * @param date
	 *            The date to format.
	 * @return The parsed data object to return.
	 */
    @Deprecated
    public String formatIso8601Date(Date date) {
        return formatISO8601Date(date);
    }

    /**
     * Formats the specified date as an ISO 8601 string.
     *
     * @param date
     *            The date to format.
     *
     * @return The ISO 8601 string representing the specified date.
     */
    public static String formatISO8601Date(Date date) {
        try {
            return iso8601DateFormat.print(date.getTime());
        } catch(RuntimeException ex) {
            throw handleException(ex);
        }
    }

	/**
	 * @deprecated by the more efficient static method
	 *             {@link #parseRFC822Date(String)}
	 * 
	 * @param dateString
	 *            The date string to parse.
	 * @return The parsed Date object.
	 */
    @Deprecated
    public Date parseRfc822Date(String dateString) {
        return parseRFC822Date(dateString);
    }

    /**
     * Parses the specified date string as an RFC 822 date and returns the Date
     * object.
     *
     * @param dateString
     *            The date string to parse.
     *
     * @return The parsed Date object.
     */
    public static Date parseRFC822Date(String dateString) {
        try {
            return new Date(rfc822DateFormat.parseMillis(dateString));
        } catch(RuntimeException ex) {
            throw handleException(ex);
        }
    }

	/**
	 * @deprecated by the more efficient static method
	 *             {@link #formatRFC822Date(java.util.Date)}
	 * 
	 * @param date
	 *            The date to format.
	 * @return The RFC 822 string representing the specified date.
	 */
    @Deprecated
    public String formatRfc822Date(Date date) {
        return formatRFC822Date(date);
    }

    /**
     * Formats the specified date as an RFC 822 string.
     *
     * @param date
     *            The date to format.
     *
     * @return The RFC 822 string representing the specified date.
     */
    public static String formatRFC822Date(Date date) {
        try {
            return rfc822DateFormat.print(date.getTime());
        } catch(RuntimeException ex) {
            throw handleException(ex);
        }
    }

	/**
	 * @deprecated by the more efficient static method
	 *             {@link #parseCompressedISO8601Date(String)}
	 * 
	 * @param dateString
	 *            The date string to parse.
	 * @return The parsed Date object.
	 */
    @Deprecated
    public Date parseCompressedIso8601Date(String dateString) {
        return parseCompressedISO8601Date(dateString);
    }

    /**
     * Parses the specified date string as a compressedIso8601DateFormat ("yyyyMMdd'T'HHmmss'Z'") and returns the Date
     * object.
     *
     * @param dateString
     *            The date string to parse.
     *
     * @return The parsed Date object.
     */
    public static Date parseCompressedISO8601Date(String dateString) {
        try {
            return new Date(compressedIso8601DateFormat.parseMillis(dateString));
        } catch (RuntimeException ex) {
            throw handleException(ex);
        }
   }

	/**
	 * Parses the given date string returned by the service into a Date object.
	 * 
	 * @param dateString
	 *            The date string to parse.
	 * @return The parsed Date object.
	 */
    public static Date parseServiceSpecificDate(String dateString) {
        if (dateString == null)
            return null;
        try {
            BigDecimal dateValue = new BigDecimal(dateString);
            return new Date(dateValue.scaleByPowerOfTen(
                    DATE_MILLI_SECOND_PRECISION).longValue());
        } catch (NumberFormatException nfe) {
            throw new ClientException("Unable to parse date : "
                    + dateString, nfe);
        }
    }

	/**
	 * Formats the give date object into an Service format.
	 * 
	 * @param date
	 *            The date to format.
	 * @return The string representing the specific date.
	 */
    public static String formatServiceSpecificDate(Date date) {
        if (date == null)
            return null;
        BigDecimal dateValue = BigDecimal.valueOf(date.getTime());
        return dateValue.scaleByPowerOfTen(0 - DATE_MILLI_SECOND_PRECISION)
                .toPlainString();
    }

    public static Date cloneDate(Date date) {
        return date == null ? null : new Date(date.getTime());
    }

	/**
	 * Returns the number of days since epoch with respect to the given number of
	 * milliseconds since epoch.
	 * 
	 * @param milliSinceEpoch
	 *            millisecond since epoch.
	 * @return Number of days since epoch.
	 */
    public static long numberOfDaysSinceEpoch(long milliSinceEpoch) {
        return TimeUnit.MILLISECONDS.toDays(milliSinceEpoch);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy