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