1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #define LOG_TAG "TimeZoneNames"
17
18 #include <memory>
19
20 #include <nativehelper/JNIHelp.h>
21 #include <nativehelper/jni_macros.h>
22
23 #include <nativehelper/ScopedLocalRef.h>
24 #include <nativehelper/ScopedUtfChars.h>
25
26 #include "IcuUtilities.h"
27 #include "ScopedIcuLocale.h"
28 #include "ScopedJavaUnicodeString.h"
29 #include "unicode/calendar.h"
30 #include "unicode/timezone.h"
31 #include "unicode/tznames.h"
32
setStringArrayElement(JNIEnv * env,jobjectArray array,int i,const icu::UnicodeString & s)33 static bool setStringArrayElement(JNIEnv* env, jobjectArray array, int i, const icu::UnicodeString& s) {
34 // Don't use "GMT" string, for backwards compatibility.
35 static const icu::UnicodeString kGmt("GMT", 3, US_INV);
36 if (!s.isBogus() && !s.startsWith(kGmt)) {
37 ScopedLocalRef<jstring> javaString(env, jniCreateString(env, s.getBuffer(), s.length()));
38 if (javaString.get() == NULL) {
39 return false;
40 }
41 env->SetObjectArrayElement(array, i, javaString.get());
42 }
43 return true;
44 }
45
TimeZoneNamesNative_fillZoneStringsNative(JNIEnv * env,jclass,jstring javaLanguageTag,jobjectArray result)46 static void TimeZoneNamesNative_fillZoneStringsNative(JNIEnv* env, jclass, jstring javaLanguageTag, jobjectArray result) {
47 ScopedIcuLocale icuLocale(env, javaLanguageTag);
48 if (!icuLocale.valid()) {
49 return;
50 }
51
52 UErrorCode status = U_ZERO_ERROR;
53 std::unique_ptr<icu::TimeZoneNames> names(icu::TimeZoneNames::createInstance(icuLocale.locale(), status));
54 if (maybeThrowIcuException(env, "TimeZoneNames::createInstance", status)) {
55 return;
56 }
57
58 const UDate now(icu::Calendar::getNow());
59
60 size_t id_count = env->GetArrayLength(result);
61 for (size_t i = 0; i < id_count; ++i) {
62 ScopedLocalRef<jobjectArray> java_row(env,
63 reinterpret_cast<jobjectArray>(env->GetObjectArrayElement(result, i)));
64 ScopedLocalRef<jstring> java_zone_id(env,
65 reinterpret_cast<jstring>(env->GetObjectArrayElement(java_row.get(), 0)));
66 ScopedJavaUnicodeString zone_id(env, java_zone_id.get());
67 if (!zone_id.valid()) {
68 return;
69 }
70
71 // Canonicalize the zone ID to the one known by ICU.
72 icu::UnicodeString lookup_id;
73 icu::TimeZone::getCanonicalID(zone_id.unicodeString(), lookup_id, status);
74 if (status != U_ZERO_ERROR) {
75 // Unknown ID - just use the zone ID we have.
76 lookup_id = zone_id.unicodeString();
77 }
78
79 icu::UnicodeString long_std;
80 names->getDisplayName(lookup_id, UTZNM_LONG_STANDARD, now, long_std);
81 icu::UnicodeString short_std;
82 names->getDisplayName(lookup_id, UTZNM_SHORT_STANDARD, now, short_std);
83 icu::UnicodeString long_dst;
84 names->getDisplayName(lookup_id, UTZNM_LONG_DAYLIGHT, now, long_dst);
85 icu::UnicodeString short_dst;
86 names->getDisplayName(lookup_id, UTZNM_SHORT_DAYLIGHT, now, short_dst);
87
88 bool okay =
89 setStringArrayElement(env, java_row.get(), 1, long_std) &&
90 setStringArrayElement(env, java_row.get(), 2, short_std) &&
91 setStringArrayElement(env, java_row.get(), 3, long_dst) &&
92 setStringArrayElement(env, java_row.get(), 4, short_dst);
93 if (!okay) {
94 return;
95 }
96 }
97 }
98
99 static JNINativeMethod gMethods[] = {
100 NATIVE_METHOD(TimeZoneNamesNative, fillZoneStringsNative, "(Ljava/lang/String;[[Ljava/lang/String;)V"),
101 };
102
register_com_android_icu_text_TimeZoneNamesNative(JNIEnv * env)103 void register_com_android_icu_text_TimeZoneNamesNative(JNIEnv* env) {
104 jniRegisterNativeMethods(env, "com/android/icu/text/TimeZoneNamesNative", gMethods, NELEM(gMethods));
105 }
106