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

net.snowflake.common.core.TmExt Maven / Gradle / Ivy

There is a newer version: 5.1.4
Show newest version
/*
 * Copyright (c) 2016 Snowflake Computing Inc. All right reserved.
 */
package net.snowflake.common.core;

import java.lang.*;
import java.math.BigInteger;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.HashMap;

/**
 * This class represents decomposed time/date, similar to libc's struct tm,
 * but with additional fields for handling missing data and timezones
 */
public class TmExt
{
  public int      tm_sec;           // seconds, 0-59:  NB: NO LEAP SECONDS!
  public int      tm_min;           // minutes, 0-59
  public int      tm_hour;          // hours, 0-23
  public int      tm_mday;          // day of the month, 1-31
  public int      tm_mon;           // month, 0-11
  public int      tm_year;          // year - 1900
  public int      tm_wday;          // day of the week, 0=Sun, 6=Sat
  public int      tm_yday;          // day of the year, 0-365
  public int      tm_isdst;         // 0 - standard time, 1 - daylight saving time,
                                    // -1 - not known
  public int      tm_gmtoff;        // offset from GMT, seconds east
  public String   tm_zone;          // Abbreviated timezone/dayling savings indicator
  public long     tm_epochSec;      // epoch seconds
  public int      tm_nsec;          // nanoseconds
  public int      tm_sec_scale;     // original decimal scale of fractional seconds
  public String   tm_region;        // timezone region name
  public boolean  tm_has_offset;    // has explicit TZ offset (from TZH:TZM)
  public boolean  tm_has_epochSec;  // has explicit epoch seconds
  public boolean  tm_has_tzidx;     // source had TZIDX kludge

    // Constants
  public static final int SECONDS_IN_MINUTE = 60;
  public static final int MINUTES_IN_HOUR = 60;
  public static final int SECONDS_IN_HOUR = SECONDS_IN_MINUTE * MINUTES_IN_HOUR;
  public static final int HOURS_IN_DAY = 24;
  public static final int MINUTES_IN_DAY = HOURS_IN_DAY * MINUTES_IN_HOUR;
  public static final int SECONDS_IN_DAY = HOURS_IN_DAY * SECONDS_IN_HOUR;
  public static final int DAYS_IN_WEEK = 7;
  public static final int MONTHS_IN_YEAR = 12;
  public static final int MAX_DAYS_IN_MONTH = 31;
  public static final int MAX_DAYS_IN_YEAR = 366;
  public static final int MAX_YEAR = 9999;
  public static final int MAX_SCALE = 9;              // max scale=9, i.e. nanoseconds
  public static final int FRAC_SECONDS = 1000000000;  // fractional seconds per second
  public static final int MAX_ZONE_LEN = 5;           // max length of the timezone name
  public static final int MAX_REGION_LEN = 48;        // max length of the timezone region name

  // Limits on epoch seconds range
  public static final long EPOCH_START = -377673494400l;  // BC 9999-01-02 00:00:00
  public static final long EPOCH_END   =  253402214400l;  // AD 9999-12-31 00:00:00

  // Epoch limit for auto-scaling
  // This is epoch time for 1971-01-01 00:00:00 times 1000
  public static final long EPOCH_AUTO_LIMIT = 31536000000l;

  /** Constructor */
  public TmExt()
  {
    tm_sec = 0;
    tm_min = 0;
    tm_hour = 0;
    tm_mday = 1;
    tm_mon = 0;
    tm_year = 0;
    tm_wday = -1;   // indicates missing wday
    tm_yday = -1;   // indicates missing yday
    tm_isdst = 0;
    tm_gmtoff = 0;
    tm_zone = null;
    tm_epochSec = 0;
    tm_nsec = 0;
    tm_sec_scale = 0;
    tm_region = null;
    tm_has_offset = false;
    tm_has_epochSec = false;
    tm_has_tzidx = false;
  }

  //
  // GENERIC PROLEPTIC GEORGIAN CALENDAR COMPUTATIONS
  //

  /**
   * Check if it's a leap year in proleptic Gregorian calendar.
   * This works for 0-based years (i.e. AD 1 = year 1, 1 BC = year 0).
   *
   * @param    year (0-based) to look at
   * @return   true if it's a leap year, false otherwise.
   */
  public static boolean isLeapYear(int year)
  {
    // Hackish is-leap-year implementation from http://jsperf.com/find-leap-year/4
    return !((year & 3) != 0 || ((year & 15) != 0 && (year % 25) == 0));
  }

  public static class YearDay
  {
    public YearDay(int year_, int yday_) { year = year_; yday = yday_; }

    public int year;  // zero-based year (0 = 1BC)
    public int yday;  // day of the year (0-355)
  };

  /**
   * Returns year based on Unix Epoch day (0 = Jan 1st, 1970)
   * in proleptic Gregorian calendar.
   *
   * @param date
   *   the epoch day
   *
   * @return YearDay
   *   yday - day of the year (staring from 0)
   *   year - zero-based year (i.e. AD 1 = year 1, 1 BC = year 0)
   */
  public static YearDay yearFromDate(int date)
  {
    // move to zero-based day offset
    // number of leap days is 478 between years 0 and 1970
    date += 719528;

    // 400-year interval... can be negative
    int y400 = (date - (date < 0 ? 146096 : 0)) / 146097;

    // Remaining date is ALWAYS positive
    date -= y400 * 146097;

    // Successive adjustments for leap year in 100 and 4 year intervals
    int y100 = 0;
    int y4 = 0;
    int y1 = 0;

    if (date >= 366)
    {
        y100 = --date / 36524;
        date %= 36524;

        if (date >= 365)
        {
            y4 = ++date / 1461;
            date %= 1461;

            if (date >= 366)
            {
                y1 = --date / 365;
                date %= 365;
            }
        }
    }
    return new YearDay(y1 + 4*y4 + 100*y100 + 400*y400, date);
  }

  /**
   * Returns starting day of the year in Unix epoch (0= Jan 1st, 1970)
   * in proleptic Gregorian calendar.
   *
   * @param year
   *  zero-based year (0 = 1 BC)
   * @return
   *  the epoch day number for Jan 1st or the year
   */
  public static int yearStartDate(int year)
  {
    return 365 * year - 719528 +
      (year > 0 ? (year+3) / 4 - (year+99) / 100 + (year+399) / 400
                : year / 4 - year / 100 + year / 400);
  }

  //
  // Per-month and cumulative day counts for monts per leap and non-leap years
  //
  //                                         Jan Feb Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec
  private static final int s_mdays[]  = {     31, 28, 31,  30,  31,  30,  31,  31,  30,  31,  30,  31 };
  private static final int s_cdays[]  = {  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
  private static final int s_lmdays[] = {     31, 29, 31,  30,  31,  30,  31,  31,  30,  31,  30,  31 };
  private static final int s_lcdays[] = {  0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };

  /**
   * Returns month # based on day of the year
   *
   * @param yday
   *   day # in the year (staring from 0)
   * @param leap
   *   true for leap years
   * @return
   *   month number (0=Jan ... 11=Dec)
   */
  public static int monthFromYday(int yday, boolean leap)
  {
    assert yday < MAX_DAYS_IN_YEAR;

    // The algorithm computes month as m = day/31 and then adjusts up 1 month
    int m = yday / 31;
    int d = leap ? s_lcdays[m + 1] : s_cdays[m + 1];
    if (yday >= d)
      m++;
    return m;
  }

  /**
   * Returns day of the month by day of the year and month
   *
   * @param yday
   *  Day of the year (starting from 0)
   * @param month
   *  Month  (0-11)
   * @param leap
   *  True for leap years
   * @return
   *  Day of the month (0-30)
   */
  public static int mdayFromYday(int yday, int month, boolean leap)
  {
    assert 0 <= yday && yday < MAX_DAYS_IN_YEAR;
    assert 0 <= month && month < MONTHS_IN_YEAR;
    return yday - (leap ? s_lcdays[month] : s_cdays[month]);
  }

  /**
   * Compute American-style (Sunday = 0) day of the week from
   * Unix epoch day (0 = Jan 1st 1970)
   *
   * @param date
   *  Unix epoch day
   * @return
   *  the day of the week (0=Sunday)
   */
  public static int dayOfWeek(int date)
  {
    date += 4;
    if (date < 0)
      date += 1879048192;   // 2^28 * 7
    return date % 7;
  }

  /*
   * Returns day of the year by month and day of the month
   *
   * @param month
   *  Month of the year (0-11)
   * @param mday
   *  Day of the month (0-30)
   * @param leap
   *  True for leap years
   * @return
   *  Day of the year (0-365)
   */
  public static int ydayFromMonthDay(int month, int mday, boolean leap)
  {
    assert 0 <= mday && mday < MAX_DAYS_IN_MONTH;
    assert 0 <= month && month < MONTHS_IN_YEAR;
    return mday + (leap ? s_lcdays[month] : s_cdays[month]);
  }

  /**
   * Check if the day of the month is good
   *
   * @param month
   *  month of the year (0-11)
   * @param mday
   *  day of the month (0-30)
   * @param leap
   *  true if this is a leap year
   * @return
   *  true if month and mday are valid
   */
  public static boolean isGoodMonthDay(int month, int mday, boolean leap)
  {
    return mday < (leap ? s_lmdays[month] : s_mdays[month]);
  }



//
// ================ XP-LIKE SET/GET FUNCTIONS ================
// DISABLED FOR NOW
//
//  /**
//   * Set DATE fields from an epoch date (0th day = Jan 1st 1970)
//   */
//  void setDate(int date)
//  {
//    // Day of the week
//    tm_wday = dayOfWeek(date);
//
//    // Year & day of the year
//    YearDay yd = yearFromDate(date);
//    tm_yday = yd.yday;
//    tm_year = yd.year - 1900;
//
//    // Month & day of the month
//    boolean leap = isLeapYear(yd.year);
//    tm_mon = monthFromYday(yd.yday, leap);
//    tm_mday = 1 + mdayFromYday(yd.yday, tm_mon, leap);
//
//    // Set epoch seconds
//    tm_epochSec = (long)date * SECONDS_IN_DAY;
//    tm_has_epochSec = true;
//  }

   /**
    * Set time of day
    *
    * @param sec
    *  time of the day (seconds from midnight)
    */
  private void setTimeSec(long sec)
  {
    assert 0 <= sec && sec < SECONDS_IN_DAY;

    // Set seconds
    tm_sec  = (int)sec % SECONDS_IN_MINUTE;
    int min = (int)sec / SECONDS_IN_MINUTE;

    tm_min  = min % MINUTES_IN_HOUR;
    tm_hour = min / MINUTES_IN_HOUR;
  }

//  /**
//   * Split seconds value into fractional and integer seconds
//   * Sets tm_nsec and tm_sec_scale fields
//   *
//   * @param val
//   *  The scaled seconds value
//   * @param scale
//   *  The scale (number of fracional decimal digits)
//   * @returns
//   *  The integer part of seconds value
//   */
//  private long splitSeconds(BigInteger val, int scale)
//  {
//    assert 0 <= scale && scale <= MAX_SCALE;
//
//    tm_sec_scale = scale;
//    tm_nsec = 0;
//    if (scale > 0)
//    {
//      BigInteger p10 = power10.sb16Table[scale];
//
//      // Divide by p10 truncating DOWN
//      if (val.signum() < 0)
//        val = val.subtract(p10).add(BigInteger.ONE);
//      val = val.divide(p10);
//
//      // Always non-negative
//      tm_nsec = val.subtract(val.multiply(p10)).intValueExact();
//    }
//    return val.longValueExact();
//  }
//
//  /**
//   * Set TIME fields from time of the day
//   *
//   * @param val
//   *  time of the day, scaled fractional seconds
//   * @param scale
//   *  scale of val
//   */
//  public void setTime(BigInteger val, int scale)
//  {
//    setTimeSec(splitSeconds(val, scale));
//  }

  /**
   * Set this structure from SFTimestamp
   *
   * NB: This relies on GeorgianCalendar, which is NOT
   *     ISO-8601 compliant proleptic Georgian calendar
   *
   * @param ts
   *  the timestamp
   * @param scale
   *  scale for fractional seconds
   * @param tz
   *  timezone to display (null to use TZ name from SFTimestamp)
   */
  public void setTimestamp(SFTimestamp ts, int scale, TimeZone tz)
  {
    assert 0 <= scale && scale <= MAX_SCALE;

    if (tz == null)
      tz = ts.getTimeZone();
    else if (!ts.getTimeZone().hasSameRules(tz))
      ts = ts.changeTimeZone(tz);
    
    tm_sec  = ts.extract(Calendar.SECOND);
    tm_min  = ts.extract(Calendar.MINUTE);
    tm_hour = ts.extract(Calendar.HOUR_OF_DAY);
    tm_mday = ts.extract(Calendar.DAY_OF_MONTH);
    tm_mon  = ts.extract(Calendar.MONTH) - 1;
    tm_year = ts.extract(Calendar.YEAR) - 1900;
    tm_wday = ts.extract(Calendar.DAY_OF_WEEK);
    tm_yday = ts.extract(Calendar.DAY_OF_YEAR) - 1;

    int dstOff = ts.extract(Calendar.DST_OFFSET) / 1000;
    tm_gmtoff =  ts.extract(Calendar.ZONE_OFFSET) / 1000 + dstOff;
    tm_isdst = (dstOff != 0) ? 1 : 0;
    tm_has_offset = true;

    tm_zone = tz.getDisplayName(dstOff != 0, TimeZone.SHORT);
    if (tm_zone != null &&
        (tm_zone.startsWith("GMT") || tm_zone.startsWith("UTC")))
      tm_zone = "GMT";

    tm_epochSec = ts.getTime() / 1000;
    tm_has_epochSec = true;
    tm_nsec = ts.getNanos();
    tm_sec_scale = scale;

    tm_region = tz.getID();
    tm_has_tzidx = false;
  }

  /**
   * Set this structure from SFDate
   *
   * NB: This relies on GeorgianCalendar, which is NOT
   *     ISO-8601 compliant proleptic Georgian calendar
   * @param d SFDate
   */
  public void setDate(SFDate d)
  {
    tm_sec = 0;
    tm_min = 0;
    tm_hour = 0;
    
    tm_mday = d.extract(Calendar.DAY_OF_MONTH);
    tm_mon  = d.extract(Calendar.MONTH) - 1;
    tm_year = d.extract(Calendar.YEAR) - 1900;
    tm_wday = d.extract(Calendar.DAY_OF_WEEK);
    tm_yday = d.extract(Calendar.DAY_OF_YEAR) - 1;

    tm_gmtoff = 0;
    tm_isdst = -1;
    tm_has_offset = false;

    tm_zone = null;

    tm_epochSec = d.getTime() / 1000;
    tm_has_epochSec = true;
    tm_nsec = 0;
    tm_sec_scale = 0;

    tm_region = null;
    tm_has_tzidx = false;
  }

  private static final int BAD_EPOCH_DATE = 0x7fffffff;

  /**
   * Get epoch day from this structure
   * Returns BAD_EPOCH_DATE on failure
   */
  private int getEpochDate()
  {
    int d;

    if (tm_has_epochSec)
    {
      if (tm_epochSec >= 0)
        d = (int)(tm_epochSec / SECONDS_IN_DAY);
      else
        d = (int)((tm_epochSec - (SECONDS_IN_DAY-1)) / SECONDS_IN_DAY);
    }
    else
    {
      int year = tm_year + 1900;

      // Compute day of the year from month and
      boolean leap = isLeapYear(year);
      if (!isGoodMonthDay(tm_mon, tm_mday-1, leap))
        return BAD_EPOCH_DATE;
      d = ydayFromMonthDay(tm_mon, tm_mday-1, leap);

      // Check that day of the year matches
      if (tm_yday > 0 && tm_yday != d + 1)
        return BAD_EPOCH_DATE;

      // Compute starting day of the year from year
      d += yearStartDate(year);

      // Check day of the week
      if (tm_wday >= 0 && tm_wday != dayOfWeek(d))
        return BAD_EPOCH_DATE;
    }
    return d;
  }

  /**
   * Get SFDate from this structure
   *
   * @return
   *  SFDate object of null if conversion is impossible
   */
  public SFDate getDate()
  {
    int d = getEpochDate();
    if (d == BAD_EPOCH_DATE)
      return null;
    return new SFDate((long) d * (1000 * SECONDS_IN_DAY));
  }

  /**
   * Set this structure from SFTime
   * @param t SFTime
   * @param scale scale
   */
  public void setTime(SFTime t, int scale)
  {
    assert 0 <= scale && scale <= MAX_SCALE;
    long nsec = t.getNanoseconds();
    int sec = (int)(nsec / FRAC_SECONDS);

    setTimeSec(sec);

    tm_mday = -1;
    tm_mon  = -1;
    tm_year = -1;
    tm_wday = -1;
    tm_yday = -1;

    tm_gmtoff =  0;
    tm_isdst = -1;
    tm_has_offset = false;

    tm_zone = null;

    tm_epochSec = sec;
    tm_has_epochSec = false;
    tm_nsec = (int) (nsec % FRAC_SECONDS);
    tm_sec_scale = scale;

    tm_region = null;
    tm_has_tzidx = false;
  }

  /**
   * Get time of the day in seconds
   * @return seconds
   */
  private int getTimeOfDay()
  {
    int s;

    if (tm_has_epochSec)
    {
      long ls = (tm_epochSec / SECONDS_IN_DAY) * SECONDS_IN_DAY;
      ls = tm_epochSec - ls;
      if (ls < 0)
        ls += SECONDS_IN_DAY;     // now ls is always positive
      assert 0 <= ls && ls < SECONDS_IN_DAY;
      s = (int) ls;
    }
    else
      s = tm_hour * SECONDS_IN_HOUR + tm_min * SECONDS_IN_MINUTE + tm_sec;
    return s;
  }

  /**
   * Get time of day as SFTime
   * @return SFTime instance
   */
  public SFTime getTime()
  {
    long ns = (long) getTimeOfDay() * FRAC_SECONDS + tm_nsec;
    return SFTime.fromNanoseconds(ns);
  }

  // The GMT timezone
  public final TimeZone s_gmtTz = TimeZone.getTimeZone("GMT");

  /**
   * Get timestamp as SFTimestamp
   *
   * @param tz
   *  the timezone to use by default
   * @return
   *  timestamp structure or null on an error
   */
  public SFTimestamp getTimestamp(TimeZone tz)
  {
    int d = getEpochDate();
    if (d == BAD_EPOCH_DATE)
      return null;

    BigDecimal ns = new BigDecimal(d);
    ns = ns.multiply(new BigDecimal((long)FRAC_SECONDS * SECONDS_IN_DAY));
    ns = ns.add(new BigDecimal((long)getTimeOfDay() * FRAC_SECONDS + tm_nsec));

    // Now we have epoch time in nanoseconds as if we had it in GMT
    SFTimestamp ts = SFTimestamp.fromNanoseconds(ns, s_gmtTz);

    // Do we have offset?
    if (tm_has_offset)
    {
      int tzidx = (tm_gmtoff / SECONDS_IN_MINUTE) + 1440;
      tz = SFTimestamp.convertTimezoneIndexToTimeZone(tzidx);
    }

    // Do we have timezone?
    else if (tm_zone != null)
    {
      // Is it a timezone abbreviation?
      Integer tzoff = s_tzAbbr.get(tm_zone);
      if (tzoff == null)
        return null;      // uknown timezone
      
      int tzidx = 1440 + tzoff;
      tz = SFTimestamp.convertTimezoneIndexToTimeZone(tzidx);
    }

    // Move to the specified tz
    if (tz != null && !tz.hasSameRules(s_gmtTz))
    {
      // If we have time in epoch secs, no adjustment is needed, just
      // assign the proper timezone
      if (tm_has_epochSec)
        ts = ts.changeTimeZone(tz);
      else
        ts = ts.moveToTimeZone(tz);
    }
    return ts;
  }

  // Timezone abbreviations
  private static final HashMap s_tzAbbr;
  static
  {
    s_tzAbbr = new HashMap<>();

    s_tzAbbr.put(  "NZDT", +780); // + 13:00 New Zealand Daylight Time
    s_tzAbbr.put(  "IDLE", +720); // + 12:00 International Date Line, East
    s_tzAbbr.put(  "NZST", +720); // + 12:00 New Zealand Standard Time
    s_tzAbbr.put(   "NZT", +720); // + 12:00 New Zealand Time
    s_tzAbbr.put( "AESST", +660); // + 11:00 Australia Eastern Summer Standard Time
    s_tzAbbr.put( "ACSST", +630); // + 10:30 Central Australia Summer Standard Time
    s_tzAbbr.put(  "CADT", +630); // + 10:30 Central Australia Daylight Savings Time
    s_tzAbbr.put(  "SADT", +630); // + 10:30 South Australian Daylight Time
    s_tzAbbr.put(  "AEST", +600); // + 10:00 Australia Eastern Standard Time
    s_tzAbbr.put(  "EAST", +600); // + 10:00 East Australian Standard Time
    s_tzAbbr.put(   "GST", +600); // + 10:00 Guam Standard Time, USSR Zone 9
    s_tzAbbr.put(  "LIGT", +600); // + 10:00 Melbourne, Australia
    s_tzAbbr.put(  "SAST", +570); // + 09:30 South Australia Standard Time
    s_tzAbbr.put(  "CAST", +570); // + 09:30 Central Australia Standard Time
    s_tzAbbr.put( "AWSST", +540); // + 09:00 Australia Western Summer Standard Time
    s_tzAbbr.put(   "JST", +540); // + 09:00 Japan Standard Time,USSR Zone 8
    s_tzAbbr.put(   "KST", +540); // + 09:00 Korea Standard Time
    s_tzAbbr.put(   "MHT", +540); // + 09:00 Kwajalein Time
    s_tzAbbr.put(   "WDT", +540); // + 09:00 West Australian Daylight Time
    s_tzAbbr.put(    "MT", +510); // + 08:30 Moluccas Time
    s_tzAbbr.put(  "AWST", +480); // + 08:00 Australia Western Standard Time
    s_tzAbbr.put(   "CCT", +480); // + 08:00 China Coastal Time
    s_tzAbbr.put(  "WADT", +480); // + 08:00 West Australian Daylight Time
    s_tzAbbr.put(   "WST", +480); // + 08:00 West Australian Standard Time
    s_tzAbbr.put(    "JT", +450); // + 07:30 Java Time
    s_tzAbbr.put( "ALMST", +420); // + 07:00 Almaty Summer Time
    s_tzAbbr.put(  "WAST", +420); // + 07:00 West Australian Standard Time
    s_tzAbbr.put(   "CXT", +420); // + 07:00 Christmas (Island) Time
    s_tzAbbr.put(  "ALMT", +360); // + 06:00 Almaty Time
    s_tzAbbr.put(  "MAWT", +360); // + 06:00 Mawson (Antarctica) Time
    s_tzAbbr.put(   "IOT", +300); // + 05:00 Indian Chagos Time
    s_tzAbbr.put(   "MVT", +300); // + 05:00 Maldives Island Time
    s_tzAbbr.put(   "TFT", +300); // + 05:00 Kerguelen Time
    s_tzAbbr.put(   "AFT", +270); // + 04:30 Afganistan Time
  //s_tzAbbr.put(  "EAST", +240); // + 04:00 Antananarivo Savings Time  // DUPLICATE!
    s_tzAbbr.put(   "MUT", +240); // + 04:00 Mauritius Island Time
    s_tzAbbr.put(   "RET", +240); // + 04:00 Reunion Island Time
    s_tzAbbr.put(   "SCT", +240); // + 04:00 Mahe Island Time
    s_tzAbbr.put(    "IT", +210); // + 03:30 Iran Time
    s_tzAbbr.put(   "EAT", +180); // + 03:00 Antananarivo, Comoro Time
    s_tzAbbr.put(    "BT", +180); // + 03:00 Baghdad Time
    s_tzAbbr.put("EETDST", +180); // + 03:00 Eastern Europe Daylight Savings Time
    s_tzAbbr.put(   "HMT", +180); // + 03:00 Hellas Mediterranean Time (?)
    s_tzAbbr.put(  "BDST", +120); // + 02:00 British Double Standard Time
    s_tzAbbr.put(  "CEST", +120); // + 02:00 Central European Savings Time
    s_tzAbbr.put("CETDST", +120); // + 02:00 Central European Daylight Savings Time
    s_tzAbbr.put(   "EET", +120); // + 02:00 Eastern Europe, USSR Zone 1
    s_tzAbbr.put(   "FWT", +120); // + 02:00 French Winter Time
    s_tzAbbr.put(   "IST", +120); // + 02:00 Israel Standard Time
    s_tzAbbr.put(  "MEST", +120); // + 02:00 Middle Europe Summer Time
    s_tzAbbr.put("METDST", +120); // + 02:00 Middle Europe Daylight Time
    s_tzAbbr.put(   "SST", +120); // + 02:00 Swedish Summer Time
    s_tzAbbr.put(   "BST",  +60); // + 01:00 British Summer Time
    s_tzAbbr.put(   "CET",  +60); // + 01:00 Central European Time
    s_tzAbbr.put(   "DNT",  +60); // + 01:00 Dansk Normal Tid
    s_tzAbbr.put(   "FST",  +60); // + 01:00 French Summer Time
    s_tzAbbr.put(   "MET",  +60); // + 01:00 Middle Europe Time
    s_tzAbbr.put(  "MEWT",  +60); // + 01:00 Middle Europe Winter Time
    s_tzAbbr.put(   "MEZ",  +60); // + 01:00 Middle Europe Zone
    s_tzAbbr.put(   "NOR",  +60); // + 01:00 Norway Standard Time
    s_tzAbbr.put(   "SET",  +60); // + 01:00 Seychelles Time
    s_tzAbbr.put(   "SWT",  +60); // + 01:00 Swedish Winter Time
    s_tzAbbr.put("WETDST",  +60); // + 01:00 Western Europe Daylight Savings Time
    s_tzAbbr.put(   "GMT",   +0); // + 00:00 Greenwich Mean Time
    s_tzAbbr.put(    "UT",   +0); // + 00:00 Universal Time
    s_tzAbbr.put(   "UTC",   +0); // + 00:00 Universal Time, Coordinated
    s_tzAbbr.put(     "Z",   +0); // + 00:00 Same as UTC
    s_tzAbbr.put(  "ZULU",   +0); // + 00:00 Same as UTC
    s_tzAbbr.put(   "WET",   +0); // + 00:00 Western Europe
    s_tzAbbr.put(   "WAT",  -60); // - 01:00 West Africa Time
    s_tzAbbr.put(   "NDT", -150); // - 02:30 Newfoundland Daylight Time
    s_tzAbbr.put(   "ADT", -180); // - 03:00 Atlantic Daylight Time
    s_tzAbbr.put(   "AWT", -180); // - 03:00 (unknown)
    s_tzAbbr.put(   "NFT", -210); // - 03:30 Newfoundland Standard Time
    s_tzAbbr.put(   "NST", -210); // - 03:30 Newfoundland Standard Time
    s_tzAbbr.put(   "AST", -240); // - 04:00 Atlantic Standard Time (Canada)
    s_tzAbbr.put(  "ACST", -240); // - 04:00 Atlantic/Porto Acre Summer Time
    s_tzAbbr.put(   "ACT", -300); // - 05:00 Atlantic/Porto Acre Standard Time
    s_tzAbbr.put(   "EDT", -240); // - 04:00 Eastern Daylight Time
    s_tzAbbr.put(   "CDT", -300); // - 05:00 Central Daylight Time
    s_tzAbbr.put(   "EST", -300); // - 05:00 Eastern Standard Time
    s_tzAbbr.put(   "CST", -360); // - 06:00 Central Standard Time
    s_tzAbbr.put(   "MDT", -360); // - 06:00 Mountain Daylight Time
    s_tzAbbr.put(   "MST", -420); // - 07:00 Mountain Standard Time
    s_tzAbbr.put(   "PDT", -420); // - 07:00 Pacific Daylight Time
    s_tzAbbr.put(  "AKDT", -480); // - 08:00 Alaska Daylight Time
    s_tzAbbr.put(   "PST", -480); // - 08:00 Pacific Standard Time
    s_tzAbbr.put(   "YDT", -480); // - 08:00 Yukon Daylight Time
    s_tzAbbr.put(  "AKST", -540); // - 09:00 Alaska Standard Time
    s_tzAbbr.put(   "HDT", -540); // - 09:00 Hawaii/Alaska Daylight Time
    s_tzAbbr.put(   "YST", -540); // - 09:00 Yukon Standard Time
    s_tzAbbr.put(  "AHST", -600); // - 10:00 Alaska-Hawaii Standard Time
    s_tzAbbr.put(   "HST", -600); // - 10:00 Hawaii Standard Time
    s_tzAbbr.put(   "CAT", -600); // - 10:00 Central Alaska Time
    s_tzAbbr.put(    "NT", -660); // - 11:00 Nome Time
    s_tzAbbr.put(  "IDLW", -720); // - 12:00 International Date Line, West
  };
};




© 2015 - 2025 Weber Informatics LLC | Privacy Policy