19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2006, The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project**
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project**
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project**
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "Log_println"
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h>
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String8.h>
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <assert.h>
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h"
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/misc.h"
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_runtime/AndroidRuntime.h"
2668dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes#include "ScopedStringChars.h"
27cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru#include "TimeUtils.h"
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <nativehelper/JNIHelp.h>
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/tztime.h>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_allDayField = 0;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_secField = 0;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_minField = 0;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_hourField = 0;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_mdayField = 0;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_monField = 0;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_yearField = 0;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_wdayField = 0;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_ydayField = 0;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_isdstField = 0;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_gmtoffField = 0;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_timezoneField = 0;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_shortMonthsField = 0;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_longMonthsField = 0;
48cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Querustatic jfieldID g_longStandaloneMonthsField = 0;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_shortWeekdaysField = 0;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_longWeekdaysField = 0;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_timeOnlyFormatField = 0;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_dateOnlyFormatField = 0;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_dateTimeFormatField = 0;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_amField = 0;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_pmField = 0;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID g_dateCommandField = 0;
574df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Projectstatic jfieldID g_localeField = 0;
584df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
594df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Projectstatic jclass g_timeClass = NULL;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline bool java2time(JNIEnv* env, Time* t, jobject o)
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t->t.tm_sec = env->GetIntField(o, g_secField);
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t->t.tm_min = env->GetIntField(o, g_minField);
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t->t.tm_hour = env->GetIntField(o, g_hourField);
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t->t.tm_mday = env->GetIntField(o, g_mdayField);
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t->t.tm_mon = env->GetIntField(o, g_monField);
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t->t.tm_year = (env->GetIntField(o, g_yearField))-1900;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t->t.tm_wday = env->GetIntField(o, g_wdayField);
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t->t.tm_yday = env->GetIntField(o, g_ydayField);
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t->t.tm_isdst = env->GetIntField(o, g_isdstField);
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t->t.tm_gmtoff = env->GetLongField(o, g_gmtoffField);
73be414332a11b539b8b7751f31a0ef584f11b48f6Elliott Hughes    bool allDay = env->GetBooleanField(o, g_allDayField);
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (allDay &&
7568dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes       ((t->t.tm_sec !=0) || (t->t.tm_min != 0) || (t->t.tm_hour != 0))) {
7668dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        jniThrowException(env, "java/lang/IllegalArgumentException",
7768dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                          "allDay is true but sec, min, hour are not 0.");
7868dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        return false;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline void time2java(JNIEnv* env, jobject o, const Time &t)
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(o, g_secField, t.t.tm_sec);
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(o, g_minField, t.t.tm_min);
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(o, g_hourField, t.t.tm_hour);
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(o, g_mdayField, t.t.tm_mday);
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(o, g_monField, t.t.tm_mon);
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(o, g_yearField, t.t.tm_year+1900);
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(o, g_wdayField, t.t.tm_wday);
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(o, g_ydayField, t.t.tm_yday);
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(o, g_isdstField, t.t.tm_isdst);
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetLongField(o, g_gmtoffField, t.t.tm_gmtoff);
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define ACQUIRE_TIMEZONE(This, t) \
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jstring timezoneString_##This \
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = (jstring) env->GetObjectField(This, g_timezoneField); \
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t.timezone = env->GetStringUTFChars(timezoneString_##This, NULL);
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define RELEASE_TIMEZONE(This, t) \
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->ReleaseStringUTFChars(timezoneString_##This, t.timezone);
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ============================================================================
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_text_format_Time_normalize(JNIEnv* env, jobject This,
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                           jboolean ignoreDst)
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Time t;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!java2time(env, &t, This)) return 0L;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ACQUIRE_TIMEZONE(This, t)
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int64_t result = t.toMillis(ignoreDst != 0);
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    time2java(env, This, t);
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RELEASE_TIMEZONE(This, t)
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return result;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_text_format_Time_switchTimezone(JNIEnv* env, jobject This,
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            jstring timezoneObject)
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Time t;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!java2time(env, &t, This)) return;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ACQUIRE_TIMEZONE(This, t)
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* timezone = env->GetStringUTFChars(timezoneObject, NULL);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t.switchTimezone(timezone);
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    time2java(env, This, t);
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->ReleaseStringUTFChars(timezoneObject, timezone);
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RELEASE_TIMEZONE(This, t)
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // we do this here because there's no point in reallocating the string
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetObjectField(This, g_timezoneField, timezoneObject);
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint android_text_format_Time_compare(JNIEnv* env, jobject clazz,
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            jobject aObject, jobject bObject)
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Time a, b;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!java2time(env, &a, aObject)) return 0;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ACQUIRE_TIMEZONE(aObject, a)
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!java2time(env, &b, bObject)) return 0;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ACQUIRE_TIMEZONE(bObject, b)
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int result = Time::compare(a, b);
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RELEASE_TIMEZONE(aObject, a)
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RELEASE_TIMEZONE(bObject, b)
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return result;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jstring android_text_format_Time_format2445(JNIEnv* env, jobject This)
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Time t;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!java2time(env, &t, This)) return env->NewStringUTF("");
165be414332a11b539b8b7751f31a0ef584f11b48f6Elliott Hughes    bool allDay = env->GetBooleanField(This, g_allDayField);
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!allDay) {
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ACQUIRE_TIMEZONE(This, t)
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool inUtc = strcmp("UTC", t.timezone) == 0;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        short buf[16];
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        t.format2445(buf, true);
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RELEASE_TIMEZONE(This, t)
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (inUtc) {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The letter 'Z' is appended to the end so allow for one
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // more character in the buffer.
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return env->NewString((jchar*)buf, 16);
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return env->NewString((jchar*)buf, 15);
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        short buf[8];
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        t.format2445(buf, false);
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return env->NewString((jchar*)buf, 8);
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jstring android_text_format_Time_format(JNIEnv* env, jobject This,
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            jstring formatObject)
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1904df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    // We only teardown and setup our 'locale' struct and other state
1914df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    // when the Java-side locale changed.  This is safe to do here
1924df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    // without locking because we're always called from Java code
1934df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    // synchronized on the class instance.
1944df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    static jobject js_locale_previous = NULL;
1954df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    static struct strftime_locale locale;
1964df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    static jstring js_mon[12], js_month[12], js_wday[7], js_weekday[7];
197cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru    static jstring js_standalone_month[12];
1984df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    static jstring js_X_fmt, js_x_fmt, js_c_fmt, js_am, js_pm, js_date_fmt;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2004df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    Time t;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!java2time(env, &t, This)) return env->NewStringUTF("");
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2034df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    jclass timeClass = g_timeClass;
2044df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    jobject js_locale = (jobject) env->GetStaticObjectField(timeClass, g_localeField);
2054df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    if (js_locale_previous != js_locale) {
2064df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        if (js_locale_previous != NULL) {
2074df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            // Free the old one.
2084df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            for (int i = 0; i < 12; i++) {
2094df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                env->ReleaseStringUTFChars(js_mon[i], locale.mon[i]);
2104df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                env->ReleaseStringUTFChars(js_month[i], locale.month[i]);
211cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru                env->ReleaseStringUTFChars(js_standalone_month[i], locale.standalone_month[i]);
2124df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                env->DeleteGlobalRef(js_mon[i]);
2134df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                env->DeleteGlobalRef(js_month[i]);
214cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru                env->DeleteGlobalRef(js_standalone_month[i]);
2154df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
2164df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
2174df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            for (int i = 0; i < 7; i++) {
2184df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                env->ReleaseStringUTFChars(js_wday[i], locale.wday[i]);
2194df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                env->ReleaseStringUTFChars(js_weekday[i], locale.weekday[i]);
2204df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                env->DeleteGlobalRef(js_wday[i]);
2214df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                env->DeleteGlobalRef(js_weekday[i]);
2224df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
2234df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
2244df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            env->ReleaseStringUTFChars(js_X_fmt, locale.X_fmt);
2254df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            env->ReleaseStringUTFChars(js_x_fmt, locale.x_fmt);
2264df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            env->ReleaseStringUTFChars(js_c_fmt, locale.c_fmt);
2274df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            env->ReleaseStringUTFChars(js_am, locale.am);
2284df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            env->ReleaseStringUTFChars(js_pm, locale.pm);
2294df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            env->ReleaseStringUTFChars(js_date_fmt, locale.date_fmt);
2304df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            env->DeleteGlobalRef(js_X_fmt);
2314df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            env->DeleteGlobalRef(js_x_fmt);
2324df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            env->DeleteGlobalRef(js_c_fmt);
2334df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            env->DeleteGlobalRef(js_am);
2344df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            env->DeleteGlobalRef(js_pm);
2354df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            env->DeleteGlobalRef(js_date_fmt);
2364df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
2374df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        js_locale_previous = js_locale;
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        jobjectArray ja;
2404df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_shortMonthsField);
2414df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        for (int i = 0; i < 12; i++) {
24299c406e42ba154584070ca7ec100e8be7ff8a800Elliott Hughes            // Calendar.JANUARY == 0.
2434df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            js_mon[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
2444df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            locale.mon[i] = env->GetStringUTFChars(js_mon[i], NULL);
2454df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2474df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_longMonthsField);
2484df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        for (int i = 0; i < 12; i++) {
24999c406e42ba154584070ca7ec100e8be7ff8a800Elliott Hughes            // Calendar.JANUARY == 0.
2504df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            js_month[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
2514df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            locale.month[i] = env->GetStringUTFChars(js_month[i], NULL);
2524df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
254cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru        ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_longStandaloneMonthsField);
255cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru        for (int i = 0; i < 12; i++) {
25699c406e42ba154584070ca7ec100e8be7ff8a800Elliott Hughes            // Calendar.JANUARY == 0.
257cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru            js_standalone_month[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i));
258cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru            locale.standalone_month[i] = env->GetStringUTFChars(js_standalone_month[i], NULL);
259cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru        }
260cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru
2614df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_shortWeekdaysField);
2624df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        for (int i = 0; i < 7; i++) {
26399c406e42ba154584070ca7ec100e8be7ff8a800Elliott Hughes            // Calendar.SUNDAY == 1, and there's an empty string in element 0.
26499c406e42ba154584070ca7ec100e8be7ff8a800Elliott Hughes            js_wday[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i + 1));
2654df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            locale.wday[i] = env->GetStringUTFChars(js_wday[i], NULL);
2664df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2684df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        ja = (jobjectArray) env->GetStaticObjectField(timeClass, g_longWeekdaysField);
2694df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        for (int i = 0; i < 7; i++) {
27099c406e42ba154584070ca7ec100e8be7ff8a800Elliott Hughes            // Calendar.SUNDAY == 1, and there's an empty string in element 0.
27199c406e42ba154584070ca7ec100e8be7ff8a800Elliott Hughes            js_weekday[i] = (jstring) env->NewGlobalRef(env->GetObjectArrayElement(ja, i + 1));
2724df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            locale.weekday[i] = env->GetStringUTFChars(js_weekday[i], NULL);
2734df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
2744df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
2754df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        js_X_fmt = (jstring) env->NewGlobalRef(env->GetStaticObjectField(
2764df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                                       timeClass, g_timeOnlyFormatField));
2774df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        locale.X_fmt = env->GetStringUTFChars(js_X_fmt, NULL);
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2794df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        js_x_fmt = (jstring) env->NewGlobalRef(env->GetStaticObjectField(
2804df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                                       timeClass, g_dateOnlyFormatField));
2814df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        locale.x_fmt = env->GetStringUTFChars(js_x_fmt, NULL);
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2834df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        js_c_fmt = (jstring) env->NewGlobalRef(env->GetStaticObjectField(
2844df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                                       timeClass, g_dateTimeFormatField));
2854df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        locale.c_fmt = env->GetStringUTFChars(js_c_fmt, NULL);
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2874df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        js_am = (jstring) env->NewGlobalRef(env->GetStaticObjectField(
2884df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                                    timeClass, g_amField));
2894df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        locale.am = env->GetStringUTFChars(js_am, NULL);
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2914df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        js_pm = (jstring) env->NewGlobalRef(env->GetStaticObjectField(
2924df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                                    timeClass, g_pmField));
2934df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        locale.pm = env->GetStringUTFChars(js_pm, NULL);
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2954df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        js_date_fmt = (jstring) env->NewGlobalRef(env->GetStaticObjectField(
2964df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                                          timeClass, g_dateCommandField));
2974df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        locale.date_fmt = env->GetStringUTFChars(js_date_fmt, NULL);
2984df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ACQUIRE_TIMEZONE(This, t)
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* format = env->GetStringUTFChars(formatObject, NULL);
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 r = t.format(format, &locale);
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->ReleaseStringUTFChars(formatObject, format);
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RELEASE_TIMEZONE(This, t)
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return env->NewStringUTF(r.string());
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jstring android_text_format_Time_toString(JNIEnv* env, jobject This)
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Time t;
31668dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes    if (!java2time(env, &t, This)) return env->NewStringUTF("");
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ACQUIRE_TIMEZONE(This, t)
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 r = t.toString();
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RELEASE_TIMEZONE(This, t)
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return env->NewStringUTF(r.string());
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_text_format_Time_setToNow(JNIEnv* env, jobject This)
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetBooleanField(This, g_allDayField, JNI_FALSE);
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Time t;
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ACQUIRE_TIMEZONE(This, t)
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t.setToNow();
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    time2java(env, This, t);
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RELEASE_TIMEZONE(This, t)
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_text_format_Time_toMillis(JNIEnv* env, jobject This,
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        jboolean ignoreDst)
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Time t;
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!java2time(env, &t, This)) return 0L;
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ACQUIRE_TIMEZONE(This, t)
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int64_t result = t.toMillis(ignoreDst != 0);
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RELEASE_TIMEZONE(This, t)
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return result;
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void android_text_format_Time_set(JNIEnv* env, jobject This, jlong millis)
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetBooleanField(This, g_allDayField, JNI_FALSE);
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Time t;
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ACQUIRE_TIMEZONE(This, t)
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    t.set(millis);
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    time2java(env, This, t);
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RELEASE_TIMEZONE(This, t)
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ============================================================================
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Just do this here because it's not worth recreating the strings
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
36868dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughesstatic int get_char(JNIEnv* env, const ScopedStringChars& s, int spos, int mul,
36968dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                    bool* thrown)
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jchar c = s[spos];
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (c >= '0' && c <= '9') {
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (c - '0') * mul;
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
3759db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru        if (!*thrown) {
37668dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            jniThrowExceptionFmt(env, "android/util/TimeFormatException",
37768dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                                 "Parse error at pos=%d", spos);
3789db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru            *thrown = true;
3799db3d07b9620b4269ab33f78604a36327e536ce1Jean-Baptiste Queru        }
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
38468dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughesstatic bool check_char(JNIEnv* env, const ScopedStringChars& s, int spos, jchar expected)
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jchar c = s[spos];
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (c != expected) {
38868dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        jniThrowExceptionFmt(env, "android/util/TimeFormatException",
38968dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                             "Unexpected character 0x%02x at pos=%d.  Expected %c.",
39068dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                             c, spos, expected);
39168dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        return false;
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return true;
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jboolean android_text_format_Time_parse(JNIEnv* env, jobject This, jstring strObj)
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jsize len = env->GetStringLength(strObj);
40068dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes    if (len < 8) {
40168dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        jniThrowException(env, "android/util/TimeFormatException",
40268dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                          "String too short -- expected at least 8 characters.");
40368dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        return false;
40468dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes    }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jboolean inUtc = false;
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
40868dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes    ScopedStringChars s(env, strObj);
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // year
41168dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes    int n;
41268dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes    bool thrown = false;
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n = get_char(env, s, 0, 1000, &thrown);
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n += get_char(env, s, 1, 100, &thrown);
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n += get_char(env, s, 2, 10, &thrown);
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n += get_char(env, s, 3, 1, &thrown);
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (thrown) return false;
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(This, g_yearField, n);
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // month
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n = get_char(env, s, 4, 10, &thrown);
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n += get_char(env, s, 5, 1, &thrown);
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n--;
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (thrown) return false;
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(This, g_monField, n);
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // day of month
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n = get_char(env, s, 6, 10, &thrown);
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n += get_char(env, s, 7, 1, &thrown);
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (thrown) return false;
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(This, g_mdayField, n);
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (len > 8) {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // T
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!check_char(env, s, 8, 'T')) return false;
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->SetBooleanField(This, g_allDayField, JNI_FALSE);
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // hour
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = get_char(env, s, 9, 10, &thrown);
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n += get_char(env, s, 10, 1, &thrown);
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (thrown) return false;
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->SetIntField(This, g_hourField, n);
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // min
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = get_char(env, s, 11, 10, &thrown);
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n += get_char(env, s, 12, 1, &thrown);
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (thrown) return false;
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->SetIntField(This, g_minField, n);
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // sec
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = get_char(env, s, 13, 10, &thrown);
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n += get_char(env, s, 14, 1, &thrown);
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (thrown) return false;
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->SetIntField(This, g_secField, n);
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (len > 15) {
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Z
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!check_char(env, s, 15, 'Z')) return false;
45968dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            inUtc = true;
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->SetBooleanField(This, g_allDayField, JNI_TRUE);
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->SetIntField(This, g_hourField, 0);
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->SetIntField(This, g_minField, 0);
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->SetIntField(This, g_secField, 0);
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(This, g_wdayField, 0);
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(This, g_ydayField, 0);
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(This, g_isdstField, -1);
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetLongField(This, g_gmtoffField, 0);
47268dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return inUtc;
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jboolean android_text_format_Time_parse3339(JNIEnv* env,
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                           jobject This,
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                           jstring strObj)
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jsize len = env->GetStringLength(strObj);
4816c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root    if (len < 10) {
4826c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root        jniThrowException(env, "android/util/TimeFormatException",
48368dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                          "String too short --- expected at least 10 characters.");
4846c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root        return false;
4856c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root    }
4866c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root
48768dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes    jboolean inUtc = false;
48868dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes
48968dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes    ScopedStringChars s(env, strObj);
49068dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // year
49268dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes    int n;
49368dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes    bool thrown = false;
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n = get_char(env, s, 0, 1000, &thrown);
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n += get_char(env, s, 1, 100, &thrown);
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n += get_char(env, s, 2, 10, &thrown);
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n += get_char(env, s, 3, 1, &thrown);
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (thrown) return false;
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(This, g_yearField, n);
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // -
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!check_char(env, s, 4, '-')) return false;
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // month
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n = get_char(env, s, 5, 10, &thrown);
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n += get_char(env, s, 6, 1, &thrown);
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    --n;
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (thrown) return false;
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(This, g_monField, n);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // -
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!check_char(env, s, 7, '-')) return false;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // day
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n = get_char(env, s, 8, 10, &thrown);
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n += get_char(env, s, 9, 1, &thrown);
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (thrown) return false;
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(This, g_mdayField, n);
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5206c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root    if (len >= 19) {
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // T
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!check_char(env, s, 10, 'T')) return false;
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
52468dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        env->SetBooleanField(This, g_allDayField, JNI_FALSE);
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // hour
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = get_char(env, s, 11, 10, &thrown);
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n += get_char(env, s, 12, 1, &thrown);
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (thrown) return false;
52968dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        int hour = n;
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // env->SetIntField(This, g_hourField, n);
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
53268dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        // :
53368dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        if (!check_char(env, s, 13, ':')) return false;
53468dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes
53568dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        // minute
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = get_char(env, s, 14, 10, &thrown);
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n += get_char(env, s, 15, 1, &thrown);
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (thrown) return false;
53968dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        int minute = n;
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // env->SetIntField(This, g_minField, n);
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
54268dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        // :
54368dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        if (!check_char(env, s, 16, ':')) return false;
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
54568dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        // second
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = get_char(env, s, 17, 10, &thrown);
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n += get_char(env, s, 18, 1, &thrown);
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (thrown) return false;
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->SetIntField(This, g_secField, n);
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5516c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root        // skip the '.XYZ' -- we don't care about subsecond precision.
5526c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root        int tz_index = 19;
5536c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root        if (tz_index < len && s[tz_index] == '.') {
5546c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root            do {
5556c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root                tz_index++;
5566c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root            } while (tz_index < len
5576c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root                && s[tz_index] >= '0'
5586c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root                && s[tz_index] <= '9');
5596c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root        }
5606c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int offset = 0;
5626c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root        if (len > tz_index) {
5636c2d4029f1fecb51e0b002e652fd18e18d059fe0Kenny Root            char c = s[tz_index];
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
56568dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            // NOTE: the offset is meant to be subtracted to get from local time
56668dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            // to UTC.  we therefore use 1 for '-' and -1 for '+'.
56768dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            switch (c) {
56868dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            case 'Z':
56968dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                // Zulu time -- UTC
57068dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                offset = 0;
57168dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                break;
57268dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            case '-':
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                offset = 1;
57468dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                break;
57568dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            case '+':
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                offset = -1;
57768dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                break;
57868dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            default:
57968dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                jniThrowExceptionFmt(env, "android/util/TimeFormatException",
58068dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                                     "Unexpected character 0x%02x at position %d.  Expected + or -",
58168dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                                     c, tz_index);
58268dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                return false;
58368dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            }
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            inUtc = true;
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
58668dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            if (offset != 0) {
58768dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                if (len < tz_index + 6) {
58868dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                    jniThrowExceptionFmt(env, "android/util/TimeFormatException",
58968dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                                         "Unexpected length; should be %d characters",
59068dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                                         tz_index + 6);
59168dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                    return false;
59268dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                }
59368dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes
59468dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                // hour
59568dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                n = get_char(env, s, tz_index + 1, 10, &thrown);
59668dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                n += get_char(env, s, tz_index + 2, 1, &thrown);
59768dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                if (thrown) return false;
59868dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                n *= offset;
59968dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                hour += n;
60068dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes
60168dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                // :
60268dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                if (!check_char(env, s, tz_index + 3, ':')) return false;
60368dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes
60468dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                // minute
60568dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                n = get_char(env, s, tz_index + 4, 10, &thrown);
60668dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                n += get_char(env, s, tz_index + 5, 1, &thrown);
60768dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                if (thrown) return false;
60868dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                n *= offset;
60968dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes                minute += n;
61068dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            }
61168dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        }
61268dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        env->SetIntField(This, g_hourField, hour);
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->SetIntField(This, g_minField, minute);
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
61568dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        if (offset != 0) {
61668dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            // we need to normalize after applying the hour and minute offsets
61768dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            android_text_format_Time_normalize(env, This, false /* use isdst */);
61868dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes            // The timezone is set to UTC in the calling Java code.
61968dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        }
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
62168dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes        env->SetBooleanField(This, g_allDayField, JNI_TRUE);
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->SetIntField(This, g_hourField, 0);
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->SetIntField(This, g_minField, 0);
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        env->SetIntField(This, g_secField, 0);
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(This, g_wdayField, 0);
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(This, g_ydayField, 0);
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetIntField(This, g_isdstField, -1);
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    env->SetLongField(This, g_gmtoffField, 0);
63168dcd1750eea33b6687f54a03b2fb7fbbb9c44c7Elliott Hughes
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return inUtc;
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ============================================================================
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * JNI registration.
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = {
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* name, signature, funcPtr */
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "normalize",               "(Z)J",                                        (void*)android_text_format_Time_normalize },
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "switchTimezone",          "(Ljava/lang/String;)V",                       (void*)android_text_format_Time_switchTimezone },
643467cabe879cb58df96f6a84879f5fb226e049aebKenny Root    { "nativeCompare",           "(Landroid/text/format/Time;Landroid/text/format/Time;)I",     (void*)android_text_format_Time_compare },
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "format1",                 "(Ljava/lang/String;)Ljava/lang/String;",      (void*)android_text_format_Time_format },
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "format2445",              "()Ljava/lang/String;",                        (void*)android_text_format_Time_format2445 },
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "toString",                "()Ljava/lang/String;",                        (void*)android_text_format_Time_toString },
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "nativeParse",             "(Ljava/lang/String;)Z",                       (void*)android_text_format_Time_parse },
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "nativeParse3339",         "(Ljava/lang/String;)Z",                       (void*)android_text_format_Time_parse3339 },
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "setToNow",                "()V",                                         (void*)android_text_format_Time_setToNow },
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "toMillis",                "(Z)J",                                        (void*)android_text_format_Time_toMillis },
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "set",                     "(J)V",                                        (void*)android_text_format_Time_set }
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_text_format_Time(JNIEnv* env)
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jclass timeClass = env->FindClass("android/text/format/Time");
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6584df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    g_timeClass = (jclass) env->NewGlobalRef(timeClass);
6594df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_allDayField = env->GetFieldID(timeClass, "allDay", "Z");
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_secField = env->GetFieldID(timeClass, "second", "I");
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_minField = env->GetFieldID(timeClass, "minute", "I");
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_hourField = env->GetFieldID(timeClass, "hour", "I");
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_mdayField = env->GetFieldID(timeClass, "monthDay", "I");
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_monField = env->GetFieldID(timeClass, "month", "I");
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_yearField = env->GetFieldID(timeClass, "year", "I");
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_wdayField = env->GetFieldID(timeClass, "weekDay", "I");
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_ydayField = env->GetFieldID(timeClass, "yearDay", "I");
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_isdstField = env->GetFieldID(timeClass, "isDst", "I");
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_gmtoffField = env->GetFieldID(timeClass, "gmtoff", "J");
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_timezoneField = env->GetFieldID(timeClass, "timezone", "Ljava/lang/String;");
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_shortMonthsField = env->GetStaticFieldID(timeClass, "sShortMonths", "[Ljava/lang/String;");
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_longMonthsField = env->GetStaticFieldID(timeClass, "sLongMonths", "[Ljava/lang/String;");
675cf4550c3198d6b3d92cdc52707fe70d7cc0caa9fJean-Baptiste Queru    g_longStandaloneMonthsField = env->GetStaticFieldID(timeClass, "sLongStandaloneMonths", "[Ljava/lang/String;");
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_shortWeekdaysField = env->GetStaticFieldID(timeClass, "sShortWeekdays", "[Ljava/lang/String;");
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_longWeekdaysField = env->GetStaticFieldID(timeClass, "sLongWeekdays", "[Ljava/lang/String;");
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_timeOnlyFormatField = env->GetStaticFieldID(timeClass, "sTimeOnlyFormat", "Ljava/lang/String;");
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_dateOnlyFormatField = env->GetStaticFieldID(timeClass, "sDateOnlyFormat", "Ljava/lang/String;");
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_dateTimeFormatField = env->GetStaticFieldID(timeClass, "sDateTimeFormat", "Ljava/lang/String;");
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_amField = env->GetStaticFieldID(timeClass, "sAm", "Ljava/lang/String;");
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_pmField = env->GetStaticFieldID(timeClass, "sPm", "Ljava/lang/String;");
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    g_dateCommandField = env->GetStaticFieldID(timeClass, "sDateCommand", "Ljava/lang/String;");
6844df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    g_localeField = env->GetStaticFieldID(timeClass, "sLocale", "Ljava/util/Locale;");
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return AndroidRuntime::registerNativeMethods(env, "android/text/format/Time", gMethods, NELEM(gMethods));
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; // namespace android
690