/* * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ import java.util.Locale; import sun.util.calendar.CalendarDate; import sun.util.calendar.CalendarSystem; import sun.util.calendar.Gregorian; /** * Time class represents the "AT" field and other time related information. * * @since 1.4 */ class Time { static final Gregorian gcal = CalendarSystem.getGregorianCalendar(); // type is wall clock time private static final int WALL = 1; // type is standard time private static final int STD = 2; // type is UTC private static final int UTC = 3; // type of representing time private int type; /** * Time from the EPOCH in milliseconds */ private long time; /** * Current time in milliseconds */ private static final long currentTime = System.currentTimeMillis(); Time() { time = 0L; } Time(long time) { this.time = time; } void setType(int type) { this.type = type; } long getTime() { return time; } int getType() { return type; } static long getCurrentTime() { return currentTime; } /** * @return true if the time is represented in wall-clock time. */ boolean isWall() { return type == WALL; } /** * @return true if the time is represented in standard time. */ boolean isSTD() { return type == STD; } /** * @return true if the time is represented in UTC time. */ boolean isUTC() { return type == UTC; } /** * Converts the type to a string that represents the type in the * SimpleTimeZone time mode. (e.g., "SimpleTimeZone.WALL_TIME"). * @return the converted string or null if the type is undefined. */ String getTypeForSimpleTimeZone() { String stz = "SimpleTimeZone."; if (isWall()) { return stz+"WALL_TIME"; } else if (isSTD()) { return stz+"STANDARD_TIME"; } else if (isUTC()) { return stz+"UTC_TIME"; } else { return null; } } /** * Converts the given Gregorian calendar field values to local time. * Local time is represented by the amount of milliseconds from * January 1, 1970 0:00 GMT. * @param year the year value * @param month the Month value * @param day the day represented by {@link RuleDay} * @param save the amount of daylight time in milliseconds * @param gmtOffset the GMT offset in milliseconds * @param time the time of the day represented by {@link Time} * @return local time */ static long getLocalTime(int year, Month month, RuleDay day, int save, int gmtOffset, Time time) { long t = time.getTime(); if (time.isSTD()) t = time.getTime() + save; else if (time.isUTC()) t = time.getTime() + save + gmtOffset; return getLocalTime(year, month, day, t); } /** * Converts the given Gregorian calendar field values to local time. * Local time is represented by the amount of milliseconds from * January 1, 1970 0:00 GMT. * @param year the year value * @param month the Month value * @param day the day value * @param time the time of the day in milliseconds * @return local time */ static long getLocalTime(int year, Month month, int day, long time) { CalendarDate date = gcal.newCalendarDate(null); date.setDate(year, month.value(), day); long millis = gcal.getTime(date); return millis + time; } /** * Equivalent to <code>getLocalTime(year, month, day, (long)time)</code>. * @param year the year value * @param month the Month value * @param day the day value * @param time the time of the day in milliseconds * @return local time */ static long getLocalTime(int year, Month month, int day, int time) { return getLocalTime(year, month, day, (long)time); } /** * Equivalent to {@link #getLocalTime(int, Month, RuleDay, int) * getLocalTime(year, month, day, (int) time)}. * @param year the year value * @param month the Month value * @param day the day represented by {@link RuleDay} * @param time the time of the day represented by {@link Time} * @return local time */ static long getLocalTime(int year, Month month, RuleDay day, long time) { return getLocalTime(year, month, day, (int) time); } /** * Converts the given Gregorian calendar field values to local time. * Local time is represented by the amount of milliseconds from * January 1, 1970 0:00 GMT. * @param year the year value * @param month the Month value * @param day the day represented by {@link RuleDay} * @param time the time of the day represented by {@link Time} * @return local time */ static long getLocalTime(int year, Month month, RuleDay day, int time) { CalendarDate cdate = gcal.newCalendarDate(null); int monthValue = month.value(); if (day.isLast()) { // e.g., "lastSun" cdate.setDate(year, monthValue, 1); cdate.setDayOfMonth(gcal.getMonthLength(cdate)); cdate = gcal.getNthDayOfWeek(-1, day.getDayOfWeekNum(), cdate); } else if (day.isLater()) { // e.g., "Sun>=1" cdate.setDate(year, monthValue, day.getDay()); cdate = gcal.getNthDayOfWeek(1, day.getDayOfWeekNum(), cdate); } else if (day.isExact()) { cdate.setDate(year, monthValue, day.getDay()); } else if (day.isEarlier()) { // e.g., "Sun<=15" cdate.setDate(year, monthValue, day.getDay()); cdate = gcal.getNthDayOfWeek(-1, day.getDayOfWeekNum(), cdate); } else { Main.panic("invalid day type: " + day); } return gcal.getTime(cdate) + time; } /** * Parses the given "AT" field and constructs a Time object. * @param the "AT" field string * @return the Time object */ static Time parse(String time) { int sign; int index = 0; Time tm; if (time.charAt(0) == '-') { sign = -1; index++; } else { sign = 1; } int val = 0; int num = 0; int countDelim = 0; while (index < time.length()) { char c = time.charAt(index++); if (c == ':') { val = val * 60 + num; countDelim++; num = 0; continue; } int d = Character.digit(c, 10); if (d == -1) { --index; break; } num = num * 10 + d; } val = val * 60 + num; // convert val to second for (; countDelim < 2; countDelim++) { val *= 60; } tm = new Time((long)val * 1000 * sign); if (index < time.length()) { char c = time.charAt(index++); if (c == 's') { tm.setType(Time.STD); } else if (c == 'u' || c == 'g' || c == 'z') { tm.setType(Time.UTC); } else if (c == 'w') { tm.setType(Time.WALL); } else { Main.panic("unknown time mode: "+c); } } else { tm.setType(Time.WALL); } return tm; } /** * Converts the given milliseconds string to a "[+-]hh:mm" string. * @param ms the milliseconds string */ static String toGMTFormat(String ms) { long sec = Long.parseLong(ms) / 1000; char sign; if (sec < 0) { sign = '-'; sec = -sec; } else { sign = '+'; } return String.format((Locale)null, "%c%02d:%02d", sign, sec/3600, (sec%3600)/60); } /** * Converts the given millisecond value to a string for a * SimpleTimeZone parameter. * @param ms the millisecond value * @return the string in a human readable form */ static String toFormedString(int ms) { StringBuilder s = new StringBuilder(); boolean minus = false; if (ms < 0) { s.append("-"); minus = true; ms = -ms; } else if (ms == 0) { return "0"; } int hour = ms / (60 * 60 * 1000); ms %= (60 * 60 * 1000); int minute = ms / (60 * 1000); if (hour != 0) { if (minus && minute != 0) { s.append("("); } s.append(Integer.toString(hour) + "*ONE_HOUR"); } if (minute != 0) { if (hour != 0) { s.append("+"); } s.append(Integer.toString(minute) + "*ONE_MINUTE"); if (minus && hour != 0) { s.append(")"); } } return s.toString(); } }