1cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn/*
2cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Copyright (C) 2011 The Android Open Source Project
3cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
4cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * you may not use this file except in compliance with the License.
6cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * You may obtain a copy of the License at
7cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
8cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
10cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
11cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * See the License for the specific language governing permissions and
14cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * limitations under the License.
15cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */
16cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
17cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornpackage android.support.v4.util;
18cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
19c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteimport android.support.annotation.RestrictTo;
20c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viverette
21cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport java.io.PrintWriter;
22cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
23c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteimport static android.support.annotation.RestrictTo.Scope.GROUP_ID;
24c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viverette
25cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn/**
260574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov * Helper for accessing features in {@link android.util.TimeUtils}
270574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov * introduced after API level 4 in a backwards compatible fashion.
280574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov *
290574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov * @hide
30cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */
31c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viverette@RestrictTo(GROUP_ID)
32c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banespublic final class TimeUtils {
33cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /** @hide Field length that can hold 999 days of time */
34cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public static final int HUNDRED_DAY_FIELD_LEN = 19;
35cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
36cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    private static final int SECONDS_PER_MINUTE = 60;
37cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    private static final int SECONDS_PER_HOUR = 60 * 60;
38cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    private static final int SECONDS_PER_DAY = 24 * 60 * 60;
39cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
40cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    private static final Object sFormatSync = new Object();
41cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+5];
42cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
43cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    static private int accumField(int amt, int suffix, boolean always, int zeropad) {
44cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (amt > 99 || (always && zeropad >= 3)) {
45cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return 3+suffix;
46cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
47cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (amt > 9 || (always && zeropad >= 2)) {
48cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return 2+suffix;
49cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
50cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (always || amt > 0) {
51cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return 1+suffix;
52cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
53cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return 0;
54cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
55cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
56cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    static private int printField(char[] formatStr, int amt, char suffix, int pos,
57cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            boolean always, int zeropad) {
58cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (always || amt > 0) {
59cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            final int startPos = pos;
60cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if ((always && zeropad >= 3) || amt > 99) {
61cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                int dig = amt/100;
62cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                formatStr[pos] = (char)(dig + '0');
63cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                pos++;
64cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                amt -= (dig*100);
65cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
66cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if ((always && zeropad >= 2) || amt > 9 || startPos != pos) {
67cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                int dig = amt/10;
68cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                formatStr[pos] = (char)(dig + '0');
69cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                pos++;
70cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                amt -= (dig*10);
71cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
72cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            formatStr[pos] = (char)(amt + '0');
73cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            pos++;
74cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            formatStr[pos] = suffix;
75cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            pos++;
76cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
77cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return pos;
78cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
79cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
80cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    private static int formatDurationLocked(long duration, int fieldLen) {
81cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (sFormatStr.length < fieldLen) {
82cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            sFormatStr = new char[fieldLen];
83cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
84cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
85cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        char[] formatStr = sFormatStr;
86cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
87cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (duration == 0) {
88cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            int pos = 0;
89cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            fieldLen -= 1;
90cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            while (pos < fieldLen) {
91cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                formatStr[pos] = ' ';
92cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
93cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            formatStr[pos] = '0';
94cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return pos+1;
95cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
96cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
97cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        char prefix;
98cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (duration > 0) {
99cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            prefix = '+';
100cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        } else {
101cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            prefix = '-';
102cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            duration = -duration;
103cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
104cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
105cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        int millis = (int)(duration%1000);
106cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        int seconds = (int) Math.floor(duration / 1000);
107cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        int days = 0, hours = 0, minutes = 0;
108cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
109cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (seconds > SECONDS_PER_DAY) {
110cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            days = seconds / SECONDS_PER_DAY;
111cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            seconds -= days * SECONDS_PER_DAY;
112cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
113cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (seconds > SECONDS_PER_HOUR) {
114cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            hours = seconds / SECONDS_PER_HOUR;
115cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            seconds -= hours * SECONDS_PER_HOUR;
116cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
117cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (seconds > SECONDS_PER_MINUTE) {
118cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            minutes = seconds / SECONDS_PER_MINUTE;
119cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            seconds -= minutes * SECONDS_PER_MINUTE;
120cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
121cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
122cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        int pos = 0;
123cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
124cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (fieldLen != 0) {
125cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            int myLen = accumField(days, 1, false, 0);
126cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            myLen += accumField(hours, 1, myLen > 0, 2);
127cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            myLen += accumField(minutes, 1, myLen > 0, 2);
128cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            myLen += accumField(seconds, 1, myLen > 0, 2);
129cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            myLen += accumField(millis, 2, true, myLen > 0 ? 3 : 0) + 1;
130cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            while (myLen < fieldLen) {
131cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                formatStr[pos] = ' ';
132cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                pos++;
133cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                myLen++;
134cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
135cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
136cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
137cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        formatStr[pos] = prefix;
138cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        pos++;
139cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
140cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        int start = pos;
141cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        boolean zeropad = fieldLen != 0;
142cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        pos = printField(formatStr, days, 'd', pos, false, 0);
143cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        pos = printField(formatStr, hours, 'h', pos, pos != start, zeropad ? 2 : 0);
144cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        pos = printField(formatStr, minutes, 'm', pos, pos != start, zeropad ? 2 : 0);
145cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        pos = printField(formatStr, seconds, 's', pos, pos != start, zeropad ? 2 : 0);
146cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        pos = printField(formatStr, millis, 'm', pos, true, (zeropad && pos != start) ? 3 : 0);
147cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        formatStr[pos] = 's';
148cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return pos + 1;
149cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
150cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
151cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /** @hide Just for debugging; not internationalized. */
152cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public static void formatDuration(long duration, StringBuilder builder) {
153cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        synchronized (sFormatSync) {
154cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            int len = formatDurationLocked(duration, 0);
155cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            builder.append(sFormatStr, 0, len);
156cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
157cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
158cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
159cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /** @hide Just for debugging; not internationalized. */
160cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public static void formatDuration(long duration, PrintWriter pw, int fieldLen) {
161cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        synchronized (sFormatSync) {
162cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            int len = formatDurationLocked(duration, fieldLen);
163cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            pw.print(new String(sFormatStr, 0, len));
164cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
165cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
166cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
167cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /** @hide Just for debugging; not internationalized. */
168cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public static void formatDuration(long duration, PrintWriter pw) {
169cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        formatDuration(duration, pw, 0);
170cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
171cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
172cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /** @hide Just for debugging; not internationalized. */
173cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public static void formatDuration(long time, long now, PrintWriter pw) {
174cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (time == 0) {
175cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            pw.print("--");
176cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return;
177cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
178cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        formatDuration(time-now, pw, 0);
179cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
180c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banes
181c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banes    private TimeUtils() {}
182cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn}
183