blob: 8c4978e2a4b3ee32a01f01d3aaf10d8cca6aa97e [file] [log] [blame]
/*
* Copyright (C) 2018 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.
*/
#include "utils/calendar/calendar-icu.h"
#include <memory>
#include "utils/base/macros.h"
#include "utils/calendar/calendar-common.h"
namespace libtextclassifier3 {
namespace {
// Make sure the constants are compatible with ICU.
#define TC3_CHECK_DAY_CONSTANT(NAME) \
static_assert(static_cast<int>(UCalendarDaysOfWeek::UCAL_##NAME) == \
static_cast<int>(DateParseData::NAME), \
"Mismatching constant value for " #NAME);
TC3_CHECK_DAY_CONSTANT(SUNDAY)
TC3_CHECK_DAY_CONSTANT(MONDAY)
TC3_CHECK_DAY_CONSTANT(TUESDAY)
TC3_CHECK_DAY_CONSTANT(WEDNESDAY)
TC3_CHECK_DAY_CONSTANT(THURSDAY)
TC3_CHECK_DAY_CONSTANT(FRIDAY)
TC3_CHECK_DAY_CONSTANT(SATURDAY)
#undef TC3_CHECK_DAY_CONSTANT
// Generic version of icu::Calendar::add with error checking.
bool CalendarAdd(UCalendarDateFields field, int value,
icu::Calendar* calendar) {
UErrorCode status = U_ZERO_ERROR;
calendar->add(field, value, status);
if (U_FAILURE(status)) {
TC3_LOG(ERROR) << "failed to add " << field;
return false;
}
return true;
}
// Generic version of icu::Calendar::get with error checking.
bool CalendarGet(UCalendarDateFields field, int* value,
icu::Calendar* calendar) {
UErrorCode status = U_ZERO_ERROR;
*value = calendar->get(field, status);
if (U_FAILURE(status)) {
TC3_LOG(ERROR) << "failed to get " << field;
return false;
}
return true;
}
// Generic version of icu::Calendar::set with error checking.
bool CalendarSet(UCalendarDateFields field, int value,
icu::Calendar* calendar) {
calendar->set(field, value);
return true;
}
} // namespace
bool Calendar::Initialize(const std::string& time_zone,
const std::string& locale, int64 time_ms_utc) {
UErrorCode status = U_ZERO_ERROR;
calendar_.reset(icu::Calendar::createInstance(
icu::Locale::createFromName(locale.c_str()), status));
if (U_FAILURE(status)) {
TC3_LOG(ERROR) << "error getting calendar instance";
return false;
}
calendar_->adoptTimeZone(
icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(time_zone)));
calendar_->setTime(time_ms_utc, status);
if (U_FAILURE(status)) {
TC3_LOG(ERROR) << "failed to set time";
return false;
}
return true;
}
bool Calendar::GetFirstDayOfWeek(int* value) const {
*value = calendar_->getFirstDayOfWeek();
return true;
}
bool Calendar::GetTimeInMillis(int64* value) const {
UErrorCode status = U_ZERO_ERROR;
*value = calendar_->getTime(status);
if (U_FAILURE(status)) {
TC3_LOG(ERROR) << "error getting time from instance";
return false;
}
return true;
}
// Below is the boilerplate code for implementing the specialisations of
// get/set/add for the various field types.
#define TC3_DEFINE_FIELD_ACCESSOR(NAME, CONST, KIND, TYPE) \
bool Calendar::KIND##NAME(TYPE value) const { \
return Calendar##KIND(UCalendarDateFields::UCAL_##CONST, value, \
calendar_.get()); \
}
#define TC3_DEFINE_ADD(NAME, CONST) \
TC3_DEFINE_FIELD_ACCESSOR(NAME, CONST, Add, int)
#define TC3_DEFINE_GET(NAME, CONST) \
TC3_DEFINE_FIELD_ACCESSOR(NAME, CONST, Get, int*)
#define TC3_DEFINE_SET(NAME, CONST) \
TC3_DEFINE_FIELD_ACCESSOR(NAME, CONST, Set, int)
TC3_DEFINE_ADD(DayOfMonth, DAY_OF_MONTH)
TC3_DEFINE_ADD(Year, YEAR)
TC3_DEFINE_ADD(Month, MONTH)
TC3_DEFINE_GET(DayOfWeek, DAY_OF_WEEK)
TC3_DEFINE_SET(ZoneOffset, ZONE_OFFSET)
TC3_DEFINE_SET(DstOffset, DST_OFFSET)
TC3_DEFINE_SET(Year, YEAR)
TC3_DEFINE_SET(Month, MONTH)
TC3_DEFINE_SET(DayOfYear, DAY_OF_YEAR)
TC3_DEFINE_SET(DayOfMonth, DAY_OF_MONTH)
TC3_DEFINE_SET(DayOfWeek, DAY_OF_WEEK)
TC3_DEFINE_SET(HourOfDay, HOUR_OF_DAY)
TC3_DEFINE_SET(Minute, MINUTE)
TC3_DEFINE_SET(Second, SECOND)
TC3_DEFINE_SET(Millisecond, MILLISECOND)
#undef TC3_DEFINE_FIELD_ACCESSOR
#undef TC3_DEFINE_ADD
#undef TC3_DEFINE_GET
#undef TC3_DEFINE_SET
} // namespace libtextclassifier3