12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */
2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/**
52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *******************************************************************************
62ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Copyright (C) 2003-2014, International Business Machines Corporation and
72ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * others. All Rights Reserved.
82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *******************************************************************************
92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Partial port from ICU4C's Grego class in i18n/gregoimp.h.
102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Methods ported, or moved here from OlsonTimeZone, initially
122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * for work on Jitterbug 5470:
132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *   tzdata2006n Brazil incorrect fall-back date 2009-mar-01
142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Only the methods necessary for that work are provided - this is not a full
152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * port of ICU4C's Grego class (yet).
162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * These utilities are used by both OlsonTimeZone and SimpleTimeZone.
182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.impl;
212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Locale;
232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/**
262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * A utility class providing proleptic Gregorian calendar functions
272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * used by time zone and calendar code.  Do not instantiate.
282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Note:  Unlike GregorianCalendar, all computations performed by this
302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * class occur in the pure proleptic GregorianCalendar.
31836e6b40a94ec3fb7545a76cb072960442b7eee9Neil Fuller * @hide Only a subset of ICU is exposed in Android
322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic class Grego {
342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // Max/min milliseconds
362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final long MIN_MILLIS = -184303902528000000L;
372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final long MAX_MILLIS = 183882168921600000L;
382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int MILLIS_PER_SECOND = 1000;
402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int MILLIS_PER_MINUTE = 60*MILLIS_PER_SECOND;
412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int MILLIS_PER_HOUR = 60*MILLIS_PER_MINUTE;
422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int MILLIS_PER_DAY = 24*MILLIS_PER_HOUR;
432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    //  January 1, 1 CE Gregorian
452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int JULIAN_1_CE = 1721426;
462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    //  January 1, 1970 CE Gregorian
482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int JULIAN_1970_CE = 2440588;
492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int[] MONTH_LENGTH = new int[] {
512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        31,28,31,30,31,30,31,31,30,31,30,31,
522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        31,29,31,30,31,30,31,31,30,31,30,31
532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    };
542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final int[] DAYS_BEFORE = new int[] {
562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        0,31,59,90,120,151,181,212,243,273,304,334,
572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        0,31,60,91,121,152,182,213,244,274,305,335 };
582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Return true if the given year is a leap year.
612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return true if the year is a leap year
632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final boolean isLeapYear(int year) {
652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // year&0x3 == year%4
662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return ((year&0x3) == 0) && ((year%100 != 0) || (year%400 == 0));
672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Return the number of days in the given month.
712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param month 0-based month, with 0==Jan
732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return the number of days in the given month
742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int monthLength(int year, int month) {
762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return MONTH_LENGTH[month + (isLeapYear(year) ? 12 : 0)];
772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Return the length of a previous month of the Gregorian calendar.
812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param month 0-based month, with 0==Jan
832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return the number of days in the month previous to the given month
842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static final int previousMonthLength(int year, int month) {
862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return (month > 0) ? monthLength(year, month-1) : 31;
872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convert a year, month, and day-of-month, given in the proleptic
912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Gregorian calendar, to 1970 epoch days.
922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param month 0-based month, with 0==Jan
942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param dom 1-based day of month
952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return the day number, with day 0 == Jan 1 1970
962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static long fieldsToDay(int year, int month, int dom) {
982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int y = year - 1;
992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long julian =
1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            365 * y + floorDivide(y, 4) + (JULIAN_1_CE - 3) +    // Julian cal
1012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            floorDivide(y, 400) - floorDivide(y, 100) + 2 +   // => Gregorian cal
1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            DAYS_BEFORE[month + (isLeapYear(year) ? 12 : 0)] + dom; // => month/dom
1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return julian - JULIAN_1970_CE; // JD => epoch day
1042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Return the day of week on the 1970-epoch day
1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param day the 1970-epoch day (integral value)
1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return the day of week
1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static int dayOfWeek(long day) {
1122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long[] remainder = new long[1];
1132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        floorDivide(day + 5 /* Calendar.THURSDAY */, 7, remainder);
1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int dayOfWeek = (int)remainder[0];
1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        dayOfWeek = (dayOfWeek == 0) ? 7 : dayOfWeek;
1162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return dayOfWeek;
1172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static int[] dayToFields(long day, int[] fields) {
1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (fields == null || fields.length < 5) {
1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            fields = new int[5];
1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Convert from 1970 CE epoch to 1 CE epoch (Gregorian calendar)
1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        day += JULIAN_1970_CE - JULIAN_1_CE;
1252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long[] rem = new long[1];
1272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long n400 = floorDivide(day, 146097, rem);
1282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long n100 = floorDivide(rem[0], 36524, rem);
1292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long n4 = floorDivide(rem[0], 1461, rem);
1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long n1 = floorDivide(rem[0], 365, rem);
1312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int year = (int)(400 * n400 + 100 * n100 + 4 * n4 + n1);
1332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int dayOfYear = (int)rem[0];
1342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (n100 == 4 || n1 == 4) {
1352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            dayOfYear = 365;    // Dec 31 at end of 4- or 400-yr cycle
1362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        else {
1382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            ++year;
1392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        boolean isLeap = isLeapYear(year);
1422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int correction = 0;
1432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int march1 = isLeap ? 60 : 59;  // zero-based DOY for March 1
1442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (dayOfYear >= march1) {
1452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            correction = isLeap ? 1 : 2;
1462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int month = (12 * (dayOfYear + correction) + 6) / 367;  // zero-based month
1482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int dayOfMonth = dayOfYear - DAYS_BEFORE[isLeap ? month + 12 : month] + 1; // one-based DOM
1492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int dayOfWeek = (int)((day + 2) % 7);  // day 0 is Monday(2)
1502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (dayOfWeek < 1 /* Sunday */) {
1512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            dayOfWeek += 7;
1522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        dayOfYear++; // 1-based day of year
1542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        fields[0] = year;
1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        fields[1] = month;
1572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        fields[2] = dayOfMonth;
1582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        fields[3] = dayOfWeek;
1592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        fields[4] = dayOfYear;
1602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return fields;
1622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
1652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convert long time to date/time fields
1662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
1672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * result[0] : year
1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * result[1] : month
1692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * result[2] : dayOfMonth
1702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * result[3] : dayOfWeek
1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * result[4] : dayOfYear
1722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * result[5] : millisecond in day
1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static int[] timeToFields(long time, int[] fields) {
1752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (fields == null || fields.length < 6) {
1762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            fields = new int[6];
1772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long[] remainder = new long[1];
1792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long day = floorDivide(time, 24*60*60*1000 /* milliseconds per day */, remainder);
1802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        dayToFields(day, fields);
1812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        fields[5] = (int)remainder[0];
1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return fields;
1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static long floorDivide(long numerator, long denominator) {
1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // We do this computation in order to handle
1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // a numerator of Long.MIN_VALUE correctly
1882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return (numerator >= 0) ?
1892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            numerator / denominator :
1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            ((numerator + 1) / denominator) - 1;
1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static long floorDivide(long numerator, long denominator, long[] remainder) {
1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (numerator >= 0) {
1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            remainder[0] = numerator % denominator;
1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return numerator / denominator;
1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        long quotient = ((numerator + 1) / denominator) - 1;
1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        remainder[0] = numerator - (quotient * denominator);
2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return quotient;
2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /*
2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the ordinal number for the specified day of week in the month.
2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The valid return value is 1, 2, 3, 4 or -1.
2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static int getDayOfWeekInMonth(int year, int month, int dayOfMonth) {
2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int weekInMonth = (dayOfMonth + 6)/7;
2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (weekInMonth == 4) {
2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (dayOfMonth + 7 > monthLength(year, month)) {
2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                weekInMonth = -1;
2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else if (weekInMonth == 5) {
2142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            weekInMonth = -1;
2152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return weekInMonth;
2172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenient method for formatting time to ISO 8601 style
2212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * date string.
2222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param time long time
2232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return ISO-8601 date string
2242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static String timeToString(long time) {
2262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int[] fields = timeToFields(time, null);
2272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int millis = fields[5];
2282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int hour = millis / MILLIS_PER_HOUR;
2292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        millis = millis % MILLIS_PER_HOUR;
2302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int min = millis / MILLIS_PER_MINUTE;
2312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        millis = millis % MILLIS_PER_MINUTE;
2322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int sec = millis / MILLIS_PER_SECOND;
2332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        millis = millis % MILLIS_PER_SECOND;
2342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return String.format((Locale)null, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ",
2362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                fields[0], fields[1] + 1, fields[2], hour, min, sec, millis);
2372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller}
239