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

com.aliyun.odps.commons.util.DateUtils Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.aliyun.odps.commons.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.SimpleTimeZone;
import java.util.TimeZone;

public class DateUtils {

  private static long TZ = +8;
  private static Calendar CAL = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
  private static Calendar GMT_CAL = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
  private static long MILLIS_OF_DAY = 24 * 60 * 60 * 1000;

  //Java unix time stamp of Current Timezone
  private static final long _0001_01_01 = getTime(1, 1, 1, 0, 0, 0);
  private static final long _0000_03_01 = getTime(0, 3, 1, 0, 0, 0);
  private static final long _1928_01_01 = getTime(1928, 1, 1, 0, 0, 0);
  private static final long _1940_06_03_01 = getTime(1940, 6, 3, 1, 0, 0);
  private static final long _1940_10_01 = getTime(1940, 10, 1, 0, 0, 0);
  private static final long _1941_03_16_01 = getTime(1941, 3, 16, 1, 0, 0);
  private static final long _1941_10_01 = getTime(1941, 10, 1, 0, 0, 0);
  private static final long _1986_05_04_01 = getTime(1986, 5, 4, 1, 0, 0);
  private static final long _1986_09_14 = getTime(1986, 9, 14, 0, 0, 0);
  private static final long _1987_04_12_01 = getTime(1987, 4, 12, 1, 0, 0);
  private static final long _1987_09_13 = getTime(1987, 9, 13, 0, 0, 0);
  private static final long _1988_04_10_01 = getTime(1988, 4, 10, 1, 0, 0);
  private static final long _1988_09_11 = getTime(1988, 9, 11, 0, 0, 0);
  private static final long _1989_04_16_01 = getTime(1989, 4, 16, 1, 0, 0);
  private static final long _1989_09_17 = getTime(1989, 9, 17, 0, 0, 0);
  private static final long _1990_04_15_01 = getTime(1990, 4, 15, 1, 0, 0);
  private static final long _1990_09_16 = getTime(1990, 9, 16, 0, 0, 0);
  private static final long _1991_04_14_01 = getTime(1991, 4, 14, 1, 0, 0);
  private static final long _1991_09_15 = getTime(1991, 9, 15, 0, 0, 0);

  //C unix time stamp of CST
  private static final long _0000_01_01_C = -62167248352L;
  private static final long _0000_03_01_C = -62162064352L;
  private static final long _0000_03_01_08_C = -62162035552L;
  private static final long _1927_12_31_23_59_59_C = -1325491553L;
  private static final long _1940_06_03_01_C = -933494400L;
  private static final long _1940_09_30_23_C = -923130000L;
  private static final long _1941_03_16_01_C = -908784000L;
  private static final long _1941_09_30_23_C = -891594000L;
  private static final long _1986_05_04_01_C = 515520000L;
  private static final long _1986_09_13_23_C = 527007600L;
  private static final long _1987_04_12_01_C = 545155200L;
  private static final long _1987_09_12_23_C = 558457200L;
  private static final long _1988_04_10_01_C = 576604800L;
  private static final long _1988_09_10_23_C = 589906800L;
  private static final long _1989_04_16_01_C = 608659200L;
  private static final long _1989_09_16_23_C = 621961200L;
  private static final long _1990_04_15_01_C = 640108800L;
  private static final long _1990_09_15_23_C = 653410800L;
  private static final long _1991_04_14_01_C = 671558400L;
  private static final long _1991_09_14_23_C = 684860400L;

  private static long getTime(int year, int month, int day, int hour, int min, int sec) {
    Calendar c = (Calendar) CAL.clone();


    c.set(Calendar.YEAR, year);
    c.set(Calendar.MONTH, month - 1);
    c.set(Calendar.DAY_OF_MONTH, day);
    c.set(Calendar.HOUR_OF_DAY, hour);
    c.set(Calendar.MINUTE, min);
    c.set(Calendar.SECOND, sec);
    c.set(Calendar.MILLISECOND, 0);
    return c.getTime().getTime();
  }

  public static long date2ms(Date date) {
    long ms;
    Calendar c = null;

    c = (Calendar) CAL.clone();
    c.setTime(date);
    ms = c.get(Calendar.MILLISECOND);

    return date2rawtime(date) * 1000 + ms;
  }

  public static Date ms2date(long ms) {
    Date d = rawtime2date(ms / 1000);
    Calendar c = (Calendar) CAL.clone();

    c.setTime(d);
    c.set(Calendar.MILLISECOND, (int) (ms % 1000));

    return c.getTime();
  }

  /**
   * @param Object
   *     of Date Class
   * @return Unix Time Stamp
   * @brief Java version of GLIBC mktime function
   *
   * 1. This algorithm is design to convert date to unix timestamp.
   * The date "0000-03-01 00:00:00" is regarded as the beginning and other
   * dates are computed based on it.
   * 2. There is no parameter verification(assuming the parameter is legal
   * and unambiguous).
   */
  public static long date2rawtime(Date date) {
    //no input parameter verification
    //get literal value of broken-down time regard less of time zone
    Calendar c = null;
    long rawtime;
    int year, mon, day, hour, min, sec;
    long ans;

    c = (Calendar) CAL.clone();
    c.setTime(date);
    c.set(Calendar.MILLISECOND, 0);

    rawtime = date.getTime();
    year = c.get(Calendar.YEAR);
    if (rawtime < _0001_01_01) {
      year = 0;
    }
    mon = c.get(Calendar.MONTH) + 1;
    day = c.get(Calendar.DAY_OF_MONTH);
    hour = c.get(Calendar.HOUR_OF_DAY);
    min = c.get(Calendar.MINUTE);
    sec = c.get(Calendar.SECOND);

    if (rawtime < _0000_03_01) {
      return _0000_01_01_C + ((((mon - 1) * 31 + (day - 1)) * 24 + hour) * 60 + min) * 60 + sec;
    }

    //get literal value of calendar time regard less of time zone
    mon = mon - 2;
    if (mon <= 0) {
      mon += 12;
      year -= 1;
    }
    ans = year / 4 - year / 100 + year / 400 + 367 * mon / 12 + day;
    ans +=
        (year * 365
         - 719499);   //719499 is a gap between 0000-03-01 00:00:00 and 1970-01-01 00:00:00 plus compensation of month
    ans = (((ans * 24 + hour) * 60 + min) * 60) + sec;

    //adjust for time zone
    ans = ans - TZ * 3600;

    //adjust for history
    if (rawtime < _1928_01_01) {
      ans = ans - 352;
    } else if (rawtime >= _1940_06_03_01 && rawtime < _1940_10_01) {
      ans = ans - 3600;
    } else if (rawtime >= _1941_03_16_01 && rawtime < _1941_10_01) {
      ans = ans - 3600;
    } else if (rawtime >= _1986_05_04_01 && rawtime < _1986_09_14) {
      ans = ans - 3600;
    } else if (rawtime >= _1987_04_12_01 && rawtime < _1987_09_13) {
      ans = ans - 3600;
    } else if (rawtime >= _1988_04_10_01 && rawtime < _1988_09_11) {
      ans = ans - 3600;
    } else if (rawtime >= _1989_04_16_01 && rawtime < _1989_09_17) {
      ans = ans - 3600;
    } else if (rawtime >= _1990_04_15_01 && rawtime < _1990_09_16) {
      ans = ans - 3600;
    } else if (rawtime >= _1991_04_14_01 && rawtime < _1991_09_15) {
      ans = ans - 3600;
    }

    return ans;
  }

  /**
   * @param rawtime
   *     Unix Time Stamp
   * @return Object of Date Class
   * @brief Java version of GLIBC localtime function
   *
   * 1. The algorithm is a reverse of mktime.
   * 2. There is no parameter verification(assuming the parameter is legal
   * and unambiguous).
   */
  public static Date rawtime2date(long rawtime) {
    int year, mon, day, hour, min, sec, leap;
    long offset;

    Calendar c = (Calendar) CAL.clone();

    if (rawtime < _0000_03_01_C) {
      offset = rawtime - _0000_01_01_C;
      sec = (int) (offset % 60);
      offset /= 60;
      min = (int) (offset % 60);
      offset /= 60;
      hour = (int) (offset % 24);
      offset /= 24;
      mon = (int) ((offset / 31) + 1);
      offset = offset % 31;
      day = (int) (offset + 1);
      year = 0;
    } else {
      offset = rawtime - _0000_03_01_08_C;
      if (rawtime > _1927_12_31_23_59_59_C) {
        offset = offset - 352;
      }
      if (rawtime >= _1940_06_03_01_C && rawtime < _1940_09_30_23_C) {
        offset = offset + 3600;
      } else if (rawtime >= _1941_03_16_01_C && rawtime < _1941_09_30_23_C) {
        offset = offset + 3600;
      } else if (rawtime >= _1986_05_04_01_C && rawtime < _1986_09_13_23_C) {
        offset = offset + 3600;
      } else if (rawtime >= _1987_04_12_01_C && rawtime < _1987_09_12_23_C) {
        offset = offset + 3600;
      } else if (rawtime >= _1988_04_10_01_C && rawtime < _1988_09_10_23_C) {
        offset = offset + 3600;
      } else if (rawtime >= _1989_04_16_01_C && rawtime < _1989_09_16_23_C) {
        offset = offset + 3600;
      } else if (rawtime >= _1990_04_15_01_C && rawtime < _1990_09_15_23_C) {
        offset = offset + 3600;
      } else if (rawtime >= _1991_04_14_01_C && rawtime < _1991_09_14_23_C) {
        offset = offset + 3600;
      }
      offset = offset + TZ * 60 * 60;

      sec = (int) (offset % 60);
      offset /= 60;
      min = (int) (offset % 60);
      offset /= 60;
      hour = (int) (offset % 24);
      offset /= 24;

      year = (int) (offset / 365);
      leap = year / 4 - year / 100 + year / 400;
      while (year * 365 + leap > offset) {
        year = year - 1;
        leap = year / 4 - year / 100 + year / 400;
      }
      offset = offset - (year * 365 + leap);

      int i = 12;
      while (offset < 367 * i / 12 - 30) {
        i--;
      }
      offset = offset - (367 * i / 12 - 30);
      mon = i + 2;
      if (mon > 12) {
        mon = mon - 12;
        year = year + 1;
      }

      day = (int) (offset + 1);
    }

    c.set(Calendar.YEAR, year);
    c.set(Calendar.MONTH, mon - 1);
    c.set(Calendar.DAY_OF_MONTH, day);
    c.set(Calendar.HOUR_OF_DAY, hour);
    c.set(Calendar.MINUTE, min);
    c.set(Calendar.SECOND, sec);
    c.set(Calendar.MILLISECOND, 0);

    return c.getTime();
  }

  // RFC 822 Date Format
  private static final String RFC822_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z";

  /**
   * Formats Date to GMT string.
   *
   * @param date
   * @return
   */
  public static String formatRfc822Date(Date date) {
    return getRfc822DateFormat().format(date);
  }

  /**
   * Parses a GMT-format string.
   *
   * @param dateString
   * @return
   * @throws ParseException
   */
  public static Date parseRfc822Date(String dateString) throws ParseException {
    return getRfc822DateFormat().parse(dateString);
  }

  private static DateFormat getRfc822DateFormat() {
    SimpleDateFormat rfc822DateFormat = new SimpleDateFormat(
        RFC822_DATE_FORMAT, Locale.US);
    rfc822DateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));

    return rfc822DateFormat;
  }

  /**
   * 计算与 1970-01-01 00:00:00 UTC  的偏移天数
   *
   * @param date
   *        时间对象
   * @return 偏移量
   */
  public static long getDayOffset(java.sql.Date date) {
    Calendar localCal = (Calendar) CAL.clone();
    Calendar gmtCal = (Calendar) GMT_CAL.clone();
    localCal.clear();
    gmtCal.clear();

    localCal.setTime(date);
    gmtCal.set(localCal.get(Calendar.YEAR), localCal.get(Calendar.MONTH), localCal.get(Calendar.DATE),
             0, 0, 0);
    return gmtCal.getTimeInMillis() / MILLIS_OF_DAY;
  }

  /**
   * 根据偏移天数,生成 java.sql.Date 时间对象
   *
   * @param offset
   *        与 1970-01-01 00:00:00 UTC  的偏移天数
   * @return Date 对象
   */
  public static java.sql.Date fromDayOffset(long offset) {
    Calendar localCal = (Calendar) CAL.clone();
    Calendar gmtCal = (Calendar) GMT_CAL.clone();
    localCal.clear();
    gmtCal.clear();

    gmtCal.setTimeInMillis(offset *  MILLIS_OF_DAY);
    localCal.set(gmtCal.get(Calendar.YEAR), gmtCal.get(Calendar.MONTH), gmtCal.get(Calendar.DATE),
               0, 0, 0);

    return new java.sql.Date(localCal.getTimeInMillis());
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy