1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package libcore.icu;
import com.ibm.icu.impl.JavaTimeZone;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.GregorianCalendar;
import com.ibm.icu.util.ULocale;
/**
* Common methods and constants for the various ICU formatters used to support
* android.text.format.DateUtils.
*/
public final class DateUtilsBridge {
// These are all public API in DateUtils. There are others, but they're either for use with
// other methods (like FORMAT_ABBREV_RELATIVE), don't internationalize (like FORMAT_CAP_AMPM),
// or have never been implemented anyway.
public static final int FORMAT_SHOW_TIME = 0x00001;
public static final int FORMAT_SHOW_WEEKDAY = 0x00002;
public static final int FORMAT_SHOW_YEAR = 0x00004;
public static final int FORMAT_NO_YEAR = 0x00008;
public static final int FORMAT_SHOW_DATE = 0x00010;
public static final int FORMAT_NO_MONTH_DAY = 0x00020;
public static final int FORMAT_12HOUR = 0x00040;
public static final int FORMAT_24HOUR = 0x00080;
public static final int FORMAT_UTC = 0x02000;
public static final int FORMAT_ABBREV_TIME = 0x04000;
public static final int FORMAT_ABBREV_WEEKDAY = 0x08000;
public static final int FORMAT_ABBREV_MONTH = 0x10000;
public static final int FORMAT_NUMERIC_DATE = 0x20000;
public static final int FORMAT_ABBREV_RELATIVE = 0x40000;
public static final int FORMAT_ABBREV_ALL = 0x80000;
/**
* Creates an immutable ICU timezone backed by the specified libcore timezone data. At the time of
* writing the libcore implementation is faster but restricted to 1902 - 2038.
* Callers must not modify the {@code tz} after calling this method.
*/
public static com.ibm.icu.util.TimeZone icuTimeZone(java.util.TimeZone tz) {
JavaTimeZone javaTimeZone = new JavaTimeZone(tz, null);
javaTimeZone.freeze(); // Optimization - allows the timezone to be copied cheaply.
return javaTimeZone;
}
public static Calendar createIcuCalendar(com.ibm.icu.util.TimeZone icuTimeZone, ULocale icuLocale,
long timeInMillis) {
Calendar calendar = new GregorianCalendar(icuTimeZone, icuLocale);
calendar.setTimeInMillis(timeInMillis);
return calendar;
}
public static String toSkeleton(Calendar calendar, int flags) {
return toSkeleton(calendar, calendar, flags);
}
public static String toSkeleton(Calendar startCalendar, Calendar endCalendar, int flags) {
if ((flags & FORMAT_ABBREV_ALL) != 0) {
flags |= FORMAT_ABBREV_MONTH | FORMAT_ABBREV_TIME | FORMAT_ABBREV_WEEKDAY;
}
String monthPart = "MMMM";
if ((flags & FORMAT_NUMERIC_DATE) != 0) {
monthPart = "M";
} else if ((flags & FORMAT_ABBREV_MONTH) != 0) {
monthPart = "MMM";
}
String weekPart = "EEEE";
if ((flags & FORMAT_ABBREV_WEEKDAY) != 0) {
weekPart = "EEE";
}
String timePart = "j"; // "j" means choose 12 or 24 hour based on current locale.
if ((flags & FORMAT_24HOUR) != 0) {
timePart = "H";
} else if ((flags & FORMAT_12HOUR) != 0) {
timePart = "h";
}
// If we've not been asked to abbreviate times, or we're using the 24-hour clock (where it
// never makes sense to leave out the minutes), include minutes. This gets us times like
// "4 PM" while avoiding times like "16" (for "16:00").
if ((flags & FORMAT_ABBREV_TIME) == 0 || (flags & FORMAT_24HOUR) != 0) {
timePart += "m";
} else {
// Otherwise, we're abbreviating a 12-hour time, and should only show the minutes
// if they're not both "00".
if (!(onTheHour(startCalendar) && onTheHour(endCalendar))) {
timePart = timePart + "m";
}
}
if (fallOnDifferentDates(startCalendar, endCalendar)) {
flags |= FORMAT_SHOW_DATE;
}
if (fallInSameMonth(startCalendar, endCalendar) && (flags & FORMAT_NO_MONTH_DAY) != 0) {
flags &= (~FORMAT_SHOW_WEEKDAY);
flags &= (~FORMAT_SHOW_TIME);
}
if ((flags & (FORMAT_SHOW_DATE | FORMAT_SHOW_TIME | FORMAT_SHOW_WEEKDAY)) == 0) {
flags |= FORMAT_SHOW_DATE;
}
// If we've been asked to show the date, work out whether we think we should show the year.
if ((flags & FORMAT_SHOW_DATE) != 0) {
if ((flags & FORMAT_SHOW_YEAR) != 0) {
// The caller explicitly wants us to show the year.
} else if ((flags & FORMAT_NO_YEAR) != 0) {
// The caller explicitly doesn't want us to show the year, even if we otherwise would.
} else if (!fallInSameYear(startCalendar, endCalendar) || !isThisYear(startCalendar)) {
flags |= FORMAT_SHOW_YEAR;
}
}
StringBuilder builder = new StringBuilder();
if ((flags & (FORMAT_SHOW_DATE | FORMAT_NO_MONTH_DAY)) != 0) {
if ((flags & FORMAT_SHOW_YEAR) != 0) {
builder.append("y");
}
builder.append(monthPart);
if ((flags & FORMAT_NO_MONTH_DAY) == 0) {
builder.append("d");
}
}
if ((flags & FORMAT_SHOW_WEEKDAY) != 0) {
builder.append(weekPart);
}
if ((flags & FORMAT_SHOW_TIME) != 0) {
builder.append(timePart);
}
return builder.toString();
}
public static int dayDistance(Calendar c1, Calendar c2) {
return c2.get(Calendar.JULIAN_DAY) - c1.get(Calendar.JULIAN_DAY);
}
private static boolean onTheHour(Calendar c) {
return c.get(Calendar.MINUTE) == 0 && c.get(Calendar.SECOND) == 0;
}
private static boolean fallOnDifferentDates(Calendar c1, Calendar c2) {
return c1.get(Calendar.YEAR) != c2.get(Calendar.YEAR) ||
c1.get(Calendar.MONTH) != c2.get(Calendar.MONTH) ||
c1.get(Calendar.DAY_OF_MONTH) != c2.get(Calendar.DAY_OF_MONTH);
}
private static boolean fallInSameMonth(Calendar c1, Calendar c2) {
return c1.get(Calendar.MONTH) == c2.get(Calendar.MONTH);
}
private static boolean fallInSameYear(Calendar c1, Calendar c2) {
return c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR);
}
private static boolean isThisYear(Calendar c) {
Calendar now = (Calendar) c.clone();
now.setTimeInMillis(System.currentTimeMillis());
return c.get(Calendar.YEAR) == now.get(Calendar.YEAR);
}
}
|