/* * Copyright 2017, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Akshay Agarwal */ #include #include #include #include #include #include #include #include #include #include #include #include U_NAMESPACE_USE static const URelativeDateTimeUnit kTimeUnitToRelativeDateTime[] = { UDAT_REL_UNIT_YEAR, UDAT_REL_UNIT_MONTH, UDAT_REL_UNIT_WEEK, UDAT_REL_UNIT_DAY, UDAT_REL_UNIT_HOUR, UDAT_REL_UNIT_MINUTE, UDAT_REL_UNIT_SECOND, }; static const UCalendarDateFields kTimeUnitToICUDateField[] = { UCAL_YEAR, UCAL_MONTH, UCAL_WEEK_OF_MONTH, UCAL_DAY_OF_WEEK, UCAL_HOUR_OF_DAY, UCAL_MINUTE, UCAL_SECOND, }; BRelativeDateTimeFormat::BRelativeDateTimeFormat() : Inherited() { Locale icuLocale(fLanguage.Code()); UErrorCode icuStatus = U_ZERO_ERROR; fFormatter = new RelativeDateTimeFormatter(icuLocale, icuStatus); if (fFormatter == NULL) { fInitStatus = B_NO_MEMORY; return; } fCalendar = new GregorianCalendar(icuStatus); if (fCalendar == NULL) { fInitStatus = B_NO_MEMORY; return; } if (!U_SUCCESS(icuStatus)) fInitStatus = B_ERROR; } BRelativeDateTimeFormat::BRelativeDateTimeFormat(const BLanguage& language, const BFormattingConventions& conventions) : Inherited(language, conventions) { Locale icuLocale(fLanguage.Code()); UErrorCode icuStatus = U_ZERO_ERROR; fFormatter = new RelativeDateTimeFormatter(icuLocale, icuStatus); if (fFormatter == NULL) { fInitStatus = B_NO_MEMORY; return; } fCalendar = new GregorianCalendar(icuStatus); if (fCalendar == NULL) { fInitStatus = B_NO_MEMORY; return; } if (!U_SUCCESS(icuStatus)) fInitStatus = B_ERROR; } BRelativeDateTimeFormat::BRelativeDateTimeFormat(const BRelativeDateTimeFormat& other) : Inherited(other), fFormatter(other.fFormatter != NULL ? new RelativeDateTimeFormatter(*other.fFormatter) : NULL), fCalendar(other.fCalendar != NULL ? new GregorianCalendar(*other.fCalendar) : NULL) { if ((fFormatter == NULL && other.fFormatter != NULL) || (fCalendar == NULL && other.fCalendar != NULL)) fInitStatus = B_NO_MEMORY; } BRelativeDateTimeFormat::~BRelativeDateTimeFormat() { delete fFormatter; delete fCalendar; } status_t BRelativeDateTimeFormat::Format(BString& string, const time_t timeValue) const { if (fFormatter == NULL) return B_NO_INIT; time_t currentTime = time(NULL); UErrorCode icuStatus = U_ZERO_ERROR; fCalendar->setTime((UDate)currentTime * 1000, icuStatus); if (!U_SUCCESS(icuStatus)) return B_ERROR; UDate UTimeValue = (UDate)timeValue * 1000; int delta = 0; int offset = 1; URelativeDateTimeUnit unit = UDAT_REL_UNIT_SECOND; for (int timeUnit = 0; timeUnit <= B_TIME_UNIT_LAST; ++timeUnit) { delta = fCalendar->fieldDifference(UTimeValue, kTimeUnitToICUDateField[timeUnit], icuStatus); if (!U_SUCCESS(icuStatus)) return B_ERROR; if (abs(delta) >= offset) { unit = kTimeUnitToRelativeDateTime[timeUnit]; break; } } UnicodeString unicodeResult; // Note: icu::RelativeDateTimeFormatter::formatNumeric() is a part of ICU Draft API // and may be changed in the future versions and was introduced in ICU 57. fFormatter->formatNumeric(delta, unit, unicodeResult, icuStatus); if (!U_SUCCESS(icuStatus)) return B_ERROR; BStringByteSink byteSink(&string); unicodeResult.toUTF8(byteSink); return B_OK; }