19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.util;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199630704ed3b265f008a8f64ec60a33cf9dcd3345Jeff Brownimport android.os.SystemClock;
20eaaf396169abdbd213565cacb37dc0c9c391b365Jeff Sharkey
2111351b655b1b0af26b7dde0bb40ec2b0d319d2a8Neil Fullerimport libcore.util.TimeZoneFinder;
2211351b655b1b0af26b7dde0bb40ec2b0d319d2a8Neil Fullerimport libcore.util.ZoneInfoDB;
2311351b655b1b0af26b7dde0bb40ec2b0d319d2a8Neil Fuller
241ebccf531d1049853b3b0630035434619682c016Dianne Hackbornimport java.io.PrintWriter;
25e8a4b66960056c2dc2c8dbb5f8df00710645cc64Jeff Sharkeyimport java.text.SimpleDateFormat;
2626e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Savilleimport java.util.Calendar;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Date;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A class containing utility methods related to time zones.
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class TimeUtils {
32a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson    /** @hide */ public TimeUtils() {}
33e8a4b66960056c2dc2c8dbb5f8df00710645cc64Jeff Sharkey    /** {@hide} */
34e8a4b66960056c2dc2c8dbb5f8df00710645cc64Jeff Sharkey    private static SimpleDateFormat sLoggingFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
35a27421a306c49fbe9b3823b30f7ab1cd58b28854Wink Saville
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Tries to return a time zone that would have had the specified offset
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and DST value at the specified moment in the specified country.
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns null if no suitable zone could be found.
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
411e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller    public static java.util.TimeZone getTimeZone(
421e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller            int offset, boolean dst, long when, String country) {
43a27421a306c49fbe9b3823b30f7ab1cd58b28854Wink Saville
441e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller        android.icu.util.TimeZone icuTimeZone = getIcuTimeZone(offset, dst, when, country);
451e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller        // We must expose a java.util.TimeZone here for API compatibility because this is a public
461e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller        // API method.
471e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller        return icuTimeZone != null ? java.util.TimeZone.getTimeZone(icuTimeZone.getID()) : null;
481e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller    }
49a27421a306c49fbe9b3823b30f7ab1cd58b28854Wink Saville
501e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller    /**
511e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller     * Tries to return a frozen ICU time zone that would have had the specified offset
521e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller     * and DST value at the specified moment in the specified country.
531e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller     * Returns null if no suitable zone could be found.
541e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller     */
551e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller    private static android.icu.util.TimeZone getIcuTimeZone(
561e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller            int offset, boolean dst, long when, String country) {
571e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller        if (country == null) {
581e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller            return null;
59a27421a306c49fbe9b3823b30f7ab1cd58b28854Wink Saville        }
60a27421a306c49fbe9b3823b30f7ab1cd58b28854Wink Saville
611e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller        android.icu.util.TimeZone bias = android.icu.util.TimeZone.getDefault();
621e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller        return TimeZoneFinder.getInstance()
631e49f6c35f2a2c0133f9e331ebb84f96d34cef4cNeil Fuller                .lookupTimeZoneByCountryAndOffset(country, offset, dst, when, bias);
64a27421a306c49fbe9b3823b30f7ab1cd58b28854Wink Saville    }
65a27421a306c49fbe9b3823b30f7ab1cd58b28854Wink Saville
66a27421a306c49fbe9b3823b30f7ab1cd58b28854Wink Saville    /**
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a String indicating the version of the time zone database currently
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in use.  The format of the string is dependent on the underlying time zone
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * database implementation, but will typically contain the year in which the database
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * was updated plus a letter from a to z indicating changes made within that year.
71a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson     *
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Time zone database updates should be expected to occur periodically due to
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * political and legal changes that cannot be anticipated in advance.  Therefore,
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when computing the UTC time for a future event, applications should be aware that
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the results may differ following a time zone database update.  This method allows
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * applications to detect that a database change has occurred, and to recalculate any
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cached times accordingly.
78a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson     *
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The time zone database may be assumed to change only when the device runtime
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is restarted.  Therefore, it is not necessary to re-query the database version
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * during the lifetime of an activity.
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String getTimeZoneDatabaseVersion() {
8448289433d878d679ecae0cd7d74371d6440285e3Elliott Hughes        return ZoneInfoDB.getInstance().getVersion();
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
861ebccf531d1049853b3b0630035434619682c016Dianne Hackborn
87b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    /** @hide Field length that can hold 999 days of time */
88b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    public static final int HUNDRED_DAY_FIELD_LEN = 19;
89a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson
901ebccf531d1049853b3b0630035434619682c016Dianne Hackborn    private static final int SECONDS_PER_MINUTE = 60;
911ebccf531d1049853b3b0630035434619682c016Dianne Hackborn    private static final int SECONDS_PER_HOUR = 60 * 60;
921ebccf531d1049853b3b0630035434619682c016Dianne Hackborn    private static final int SECONDS_PER_DAY = 24 * 60 * 60;
931ebccf531d1049853b3b0630035434619682c016Dianne Hackborn
94315c329544d7c593d1072b071cbb92d9afe74021John Reck    /** @hide */
95315c329544d7c593d1072b071cbb92d9afe74021John Reck    public static final long NANOS_PER_MS = 1000000;
96315c329544d7c593d1072b071cbb92d9afe74021John Reck
97b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    private static final Object sFormatSync = new Object();
983d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn    private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+10];
993d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn    private static char[] sTmpFormatStr = new char[HUNDRED_DAY_FIELD_LEN+10];
100eaaf396169abdbd213565cacb37dc0c9c391b365Jeff Sharkey
101b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    static private int accumField(int amt, int suffix, boolean always, int zeropad) {
1023d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn        if (amt > 999) {
1033d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn            int num = 0;
1043d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn            while (amt != 0) {
1053d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                num++;
1063d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                amt /= 10;
1073d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn            }
1083d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn            return num + suffix;
1093d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn        } else {
1103d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn            if (amt > 99 || (always && zeropad >= 3)) {
1113d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                return 3+suffix;
1123d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn            }
1133d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn            if (amt > 9 || (always && zeropad >= 2)) {
1143d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                return 2+suffix;
1153d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn            }
1163d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn            if (always || amt > 0) {
1173d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                return 1+suffix;
1183d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn            }
1191ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        }
120b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        return 0;
121b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    }
122a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson
1233d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn    static private int printFieldLocked(char[] formatStr, int amt, char suffix, int pos,
124b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            boolean always, int zeropad) {
125b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        if (always || amt > 0) {
126901b3796fd0954cc4b01bf95dbcbd88d87414e84Bjorn Bringert            final int startPos = pos;
1273d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn            if (amt > 999) {
1283d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                int tmp = 0;
1293d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                while (amt != 0 && tmp < sTmpFormatStr.length) {
1303d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    int dig = amt % 10;
1313d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    sTmpFormatStr[tmp] = (char)(dig + '0');
1323d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    tmp++;
1333d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    amt /= 10;
1343d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                }
1353d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                tmp--;
1363d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                while (tmp >= 0) {
1373d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    formatStr[pos] = sTmpFormatStr[tmp];
1383d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    pos++;
1393d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    tmp--;
1403d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                }
1413d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn            } else {
1423d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                if ((always && zeropad >= 3) || amt > 99) {
1433d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    int dig = amt/100;
1443d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    formatStr[pos] = (char)(dig + '0');
1453d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    pos++;
1463d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    amt -= (dig*100);
1473d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                }
1483d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                if ((always && zeropad >= 2) || amt > 9 || startPos != pos) {
1493d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    int dig = amt/10;
1503d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    formatStr[pos] = (char)(dig + '0');
1513d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    pos++;
1523d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                    amt -= (dig*10);
1533d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                }
1543d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn                formatStr[pos] = (char)(amt + '0');
155b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn                pos++;
156b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            }
157b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            formatStr[pos] = suffix;
158b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            pos++;
1591ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        }
160b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        return pos;
1611ebccf531d1049853b3b0630035434619682c016Dianne Hackborn    }
162a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson
163b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    private static int formatDurationLocked(long duration, int fieldLen) {
164b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        if (sFormatStr.length < fieldLen) {
165b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            sFormatStr = new char[fieldLen];
166b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        }
167a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson
168b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        char[] formatStr = sFormatStr;
169a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson
1701ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        if (duration == 0) {
171b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            int pos = 0;
172b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            fieldLen -= 1;
173b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            while (pos < fieldLen) {
17447f13e7c52b260858bab42217d2101741ea8bc46Jozef BABJAK                formatStr[pos++] = ' ';
175b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            }
176b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            formatStr[pos] = '0';
177b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            return pos+1;
1781ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        }
179a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson
180b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        char prefix;
1811ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        if (duration > 0) {
182b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            prefix = '+';
1831ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        } else {
184b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            prefix = '-';
1851ebccf531d1049853b3b0630035434619682c016Dianne Hackborn            duration = -duration;
1861ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        }
1871ebccf531d1049853b3b0630035434619682c016Dianne Hackborn
1881ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        int millis = (int)(duration%1000);
1891ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        int seconds = (int) Math.floor(duration / 1000);
1901ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        int days = 0, hours = 0, minutes = 0;
1911ebccf531d1049853b3b0630035434619682c016Dianne Hackborn
192f9a80cbbfe5585772ea16fddfeb728c74bc04b2dMitchell Wills        if (seconds >= SECONDS_PER_DAY) {
1931ebccf531d1049853b3b0630035434619682c016Dianne Hackborn            days = seconds / SECONDS_PER_DAY;
1941ebccf531d1049853b3b0630035434619682c016Dianne Hackborn            seconds -= days * SECONDS_PER_DAY;
1951ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        }
196f9a80cbbfe5585772ea16fddfeb728c74bc04b2dMitchell Wills        if (seconds >= SECONDS_PER_HOUR) {
1971ebccf531d1049853b3b0630035434619682c016Dianne Hackborn            hours = seconds / SECONDS_PER_HOUR;
1981ebccf531d1049853b3b0630035434619682c016Dianne Hackborn            seconds -= hours * SECONDS_PER_HOUR;
1991ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        }
200f9a80cbbfe5585772ea16fddfeb728c74bc04b2dMitchell Wills        if (seconds >= SECONDS_PER_MINUTE) {
2011ebccf531d1049853b3b0630035434619682c016Dianne Hackborn            minutes = seconds / SECONDS_PER_MINUTE;
2021ebccf531d1049853b3b0630035434619682c016Dianne Hackborn            seconds -= minutes * SECONDS_PER_MINUTE;
2031ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        }
2041ebccf531d1049853b3b0630035434619682c016Dianne Hackborn
205b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        int pos = 0;
206a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson
207b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        if (fieldLen != 0) {
208b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            int myLen = accumField(days, 1, false, 0);
209b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            myLen += accumField(hours, 1, myLen > 0, 2);
210b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            myLen += accumField(minutes, 1, myLen > 0, 2);
211b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            myLen += accumField(seconds, 1, myLen > 0, 2);
212b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            myLen += accumField(millis, 2, true, myLen > 0 ? 3 : 0) + 1;
213b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            while (myLen < fieldLen) {
214b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn                formatStr[pos] = ' ';
215b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn                pos++;
216b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn                myLen++;
217b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            }
2181ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        }
219a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson
220b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        formatStr[pos] = prefix;
221b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        pos++;
222a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson
223b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        int start = pos;
224b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        boolean zeropad = fieldLen != 0;
2253d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn        pos = printFieldLocked(formatStr, days, 'd', pos, false, 0);
2263d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn        pos = printFieldLocked(formatStr, hours, 'h', pos, pos != start, zeropad ? 2 : 0);
2273d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn        pos = printFieldLocked(formatStr, minutes, 'm', pos, pos != start, zeropad ? 2 : 0);
2283d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn        pos = printFieldLocked(formatStr, seconds, 's', pos, pos != start, zeropad ? 2 : 0);
2293d1933c45fe9ba2389ebd166d96abeceab1971d1Dianne Hackborn        pos = printFieldLocked(formatStr, millis, 'm', pos, true, (zeropad && pos != start) ? 3 : 0);
230b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        formatStr[pos] = 's';
231b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        return pos + 1;
232b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    }
233a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson
234b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    /** @hide Just for debugging; not internationalized. */
235b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    public static void formatDuration(long duration, StringBuilder builder) {
236b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        synchronized (sFormatSync) {
237b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            int len = formatDurationLocked(duration, 0);
238b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            builder.append(sFormatStr, 0, len);
2391ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        }
2401ebccf531d1049853b3b0630035434619682c016Dianne Hackborn    }
2411ebccf531d1049853b3b0630035434619682c016Dianne Hackborn
242b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    /** @hide Just for debugging; not internationalized. */
24371a9531806d9d37f5482c4d242f95416c04715bfKweku Adams    public static void formatDuration(long duration, StringBuilder builder, int fieldLen) {
24471a9531806d9d37f5482c4d242f95416c04715bfKweku Adams        synchronized (sFormatSync) {
24571a9531806d9d37f5482c4d242f95416c04715bfKweku Adams            int len = formatDurationLocked(duration, fieldLen);
24671a9531806d9d37f5482c4d242f95416c04715bfKweku Adams            builder.append(sFormatStr, 0, len);
24771a9531806d9d37f5482c4d242f95416c04715bfKweku Adams        }
24871a9531806d9d37f5482c4d242f95416c04715bfKweku Adams    }
24971a9531806d9d37f5482c4d242f95416c04715bfKweku Adams
25071a9531806d9d37f5482c4d242f95416c04715bfKweku Adams    /** @hide Just for debugging; not internationalized. */
251b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    public static void formatDuration(long duration, PrintWriter pw, int fieldLen) {
252b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        synchronized (sFormatSync) {
253b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            int len = formatDurationLocked(duration, fieldLen);
254b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn            pw.print(new String(sFormatStr, 0, len));
255b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        }
256b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    }
2571ebccf531d1049853b3b0630035434619682c016Dianne Hackborn
2581ebccf531d1049853b3b0630035434619682c016Dianne Hackborn    /** @hide Just for debugging; not internationalized. */
259d0fff2eac4fe878071dd170e885a4a9c0a1b20e8Jeff Sharkey    public static String formatDuration(long duration) {
260d0fff2eac4fe878071dd170e885a4a9c0a1b20e8Jeff Sharkey        synchronized (sFormatSync) {
261d0fff2eac4fe878071dd170e885a4a9c0a1b20e8Jeff Sharkey            int len = formatDurationLocked(duration, 0);
262d0fff2eac4fe878071dd170e885a4a9c0a1b20e8Jeff Sharkey            return new String(sFormatStr, 0, len);
263d0fff2eac4fe878071dd170e885a4a9c0a1b20e8Jeff Sharkey        }
264d0fff2eac4fe878071dd170e885a4a9c0a1b20e8Jeff Sharkey    }
265d0fff2eac4fe878071dd170e885a4a9c0a1b20e8Jeff Sharkey
266d0fff2eac4fe878071dd170e885a4a9c0a1b20e8Jeff Sharkey    /** @hide Just for debugging; not internationalized. */
267b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    public static void formatDuration(long duration, PrintWriter pw) {
268b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        formatDuration(duration, pw, 0);
269b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    }
270a0f8bc51aff98c2e23e73069e447f63397471a0aJesse Wilson
271b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn    /** @hide Just for debugging; not internationalized. */
2721ebccf531d1049853b3b0630035434619682c016Dianne Hackborn    public static void formatDuration(long time, long now, PrintWriter pw) {
2731ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        if (time == 0) {
2741ebccf531d1049853b3b0630035434619682c016Dianne Hackborn            pw.print("--");
2751ebccf531d1049853b3b0630035434619682c016Dianne Hackborn            return;
2761ebccf531d1049853b3b0630035434619682c016Dianne Hackborn        }
277b5e3165129a5871cf679a67d9e9323ffad3d4902Dianne Hackborn        formatDuration(time-now, pw, 0);
2781ebccf531d1049853b3b0630035434619682c016Dianne Hackborn    }
27926e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville
2809630704ed3b265f008a8f64ec60a33cf9dcd3345Jeff Brown    /** @hide Just for debugging; not internationalized. */
2819630704ed3b265f008a8f64ec60a33cf9dcd3345Jeff Brown    public static String formatUptime(long time) {
2829630704ed3b265f008a8f64ec60a33cf9dcd3345Jeff Brown        final long diff = time - SystemClock.uptimeMillis();
2839630704ed3b265f008a8f64ec60a33cf9dcd3345Jeff Brown        if (diff > 0) {
2849630704ed3b265f008a8f64ec60a33cf9dcd3345Jeff Brown            return time + " (in " + diff + " ms)";
2859630704ed3b265f008a8f64ec60a33cf9dcd3345Jeff Brown        }
2869630704ed3b265f008a8f64ec60a33cf9dcd3345Jeff Brown        if (diff < 0) {
2879630704ed3b265f008a8f64ec60a33cf9dcd3345Jeff Brown            return time + " (" + -diff + " ms ago)";
2889630704ed3b265f008a8f64ec60a33cf9dcd3345Jeff Brown        }
2899630704ed3b265f008a8f64ec60a33cf9dcd3345Jeff Brown        return time + " (now)";
2909630704ed3b265f008a8f64ec60a33cf9dcd3345Jeff Brown    }
2919630704ed3b265f008a8f64ec60a33cf9dcd3345Jeff Brown
29226e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville    /**
29326e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville     * Convert a System.currentTimeMillis() value to a time of day value like
29426e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville     * that printed in logs. MM-DD HH:MM:SS.MMM
29526e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville     *
29626e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville     * @param millis since the epoch (1/1/1970)
29726e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville     * @return String representation of the time.
29826e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville     * @hide
29926e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville     */
30026e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville    public static String logTimeOfDay(long millis) {
30126e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville        Calendar c = Calendar.getInstance();
30226e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville        if (millis >= 0) {
30326e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville            c.setTimeInMillis(millis);
30426e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville            return String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c);
30526e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville        } else {
30626e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville            return Long.toString(millis);
30726e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville        }
30826e1a02ba3183aba2ba262c6f60602e10dd792e3Wink Saville    }
309e8a4b66960056c2dc2c8dbb5f8df00710645cc64Jeff Sharkey
310e8a4b66960056c2dc2c8dbb5f8df00710645cc64Jeff Sharkey    /** {@hide} */
311e8a4b66960056c2dc2c8dbb5f8df00710645cc64Jeff Sharkey    public static String formatForLogging(long millis) {
312e8a4b66960056c2dc2c8dbb5f8df00710645cc64Jeff Sharkey        if (millis <= 0) {
313e8a4b66960056c2dc2c8dbb5f8df00710645cc64Jeff Sharkey            return "unknown";
314e8a4b66960056c2dc2c8dbb5f8df00710645cc64Jeff Sharkey        } else {
315e8a4b66960056c2dc2c8dbb5f8df00710645cc64Jeff Sharkey            return sLoggingFormat.format(new Date(millis));
316e8a4b66960056c2dc2c8dbb5f8df00710645cc64Jeff Sharkey        }
317e8a4b66960056c2dc2c8dbb5f8df00710645cc64Jeff Sharkey    }
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
319