• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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