Ticket #13679: 0001-Implement-a-formatter-for-relative-dates.patch

File 0001-Implement-a-formatter-for-relative-dates.patch, 6.1 KB (added by akshay, 3 years ago)
  • new file headers/os/locale/RelativeDateTimeFormat.h

    From b0b1daee3b32074adb0354d1f38fb7bab9cb5104 Mon Sep 17 00:00:00 2001
    From: Akshay Agarwal <agarwal.akshay.akshay8@gmail.com>
    Date: Thu, 24 Aug 2017 12:09:11 +0530
    Subject: [PATCH] Implement a formatter for relative dates.
    
    ---
     headers/os/locale/RelativeDateTimeFormat.h |  44 ++++++++
     src/kits/locale/Jamfile                    |   1 +
     src/kits/locale/RelativeDateTimeFormat.cpp | 162 +++++++++++++++++++++++++++++
     3 files changed, 207 insertions(+)
     create mode 100644 headers/os/locale/RelativeDateTimeFormat.h
     create mode 100644 src/kits/locale/RelativeDateTimeFormat.cpp
    
    diff --git a/headers/os/locale/RelativeDateTimeFormat.h b/headers/os/locale/RelativeDateTimeFormat.h
    new file mode 100644
    index 0000000..dce4866
    - +  
     1/*
     2 * Copyright 2017, Haiku, Inc. All Rights Reserved.
     3 * Distributed under the terms of the MIT License.
     4 *
     5 * Authors:
     6 *      Akshay Agarwal <agarwal.akshay.akshay8@gmail.com>
     7 */
     8#ifndef _B_RELATIVE_DATE_TIME_FORMAT_H_
     9#define _B_RELATIVE_DATE_TIME_FORMAT_H_
     10
     11
     12#include <Format.h>
     13#include <SupportDefs.h>
     14
     15
     16class BString;
     17
     18#ifndef U_ICU_NAMESPACE
     19  #define U_ICU_NAMESPACE icu
     20#endif
     21namespace U_ICU_NAMESPACE {
     22    class GregorianCalendar;
     23    class RelativeDateTimeFormatter;
     24}
     25
     26
     27class BRelativeDateTimeFormat: public BFormat {
     28    typedef BFormat             Inherited;
     29public:
     30                                BRelativeDateTimeFormat();
     31                                BRelativeDateTimeFormat(const BLanguage& language,
     32                                    const BFormattingConventions& conventions);
     33                                BRelativeDateTimeFormat(const BRelativeDateTimeFormat& other);
     34            virtual             ~BRelativeDateTimeFormat();
     35
     36            status_t            Format(BString& string, const time_t timeValue) const;
     37
     38private:
     39            U_ICU_NAMESPACE::RelativeDateTimeFormatter* fFormatter;
     40            U_ICU_NAMESPACE::GregorianCalendar* fCalendar;
     41};
     42
     43
     44#endif  // _B_RELATIVE_DATE_TIME_FORMAT_H_
  • src/kits/locale/Jamfile

    diff --git a/src/kits/locale/Jamfile b/src/kits/locale/Jamfile
    index 73b7646..057687f 100644
    a b local sources =  
    3434    TimeUnitFormat.cpp
    3535    Format.cpp # Used by some of the above.
    3636    UnicodeChar.cpp # Already used in FirstBootPrompt.
     37    RelativeDateTimeFormat.cpp
    3738    ;
    3839
    3940local architectureObject ;
  • new file src/kits/locale/RelativeDateTimeFormat.cpp

    diff --git a/src/kits/locale/RelativeDateTimeFormat.cpp b/src/kits/locale/RelativeDateTimeFormat.cpp
    new file mode 100644
    index 0000000..e47576d
    - +  
     1/*
     2 * Copyright 2017, Haiku, Inc. All Rights Reserved.
     3 * Distributed under the terms of the MIT License.
     4 *
     5 * Authors:
     6 *      Akshay Agarwal <agarwal.akshay.akshay8@gmail.com>
     7 */
     8
     9
     10#include <unicode/uversion.h>
     11#include <RelativeDateTimeFormat.h>
     12
     13#include <time.h>
     14
     15#include <unicode/gregocal.h>
     16#include <unicode/reldatefmt.h>
     17#include <unicode/utypes.h>
     18
     19#include <ICUWrapper.h>
     20
     21#include <Language.h>
     22#include <Locale.h>
     23#include <LocaleRoster.h>
     24#include <TimeUnitFormat.h>
     25
     26
     27static const URelativeDateTimeUnit kTimeUnitToRelativeDateTime[] = {
     28    UDAT_REL_UNIT_YEAR,
     29    UDAT_REL_UNIT_MONTH,
     30    UDAT_REL_UNIT_WEEK,
     31    UDAT_REL_UNIT_DAY,
     32    UDAT_REL_UNIT_HOUR,
     33    UDAT_REL_UNIT_MINUTE,
     34    UDAT_REL_UNIT_SECOND,
     35};
     36
     37
     38static const UCalendarDateFields kTimeUnitToICUDateField[] = {
     39    UCAL_YEAR,
     40    UCAL_MONTH,
     41    UCAL_WEEK_OF_MONTH,
     42    UCAL_DAY_OF_WEEK,
     43    UCAL_HOUR_OF_DAY,
     44    UCAL_MINUTE,
     45    UCAL_SECOND,
     46};
     47
     48
     49BRelativeDateTimeFormat::BRelativeDateTimeFormat()
     50    : Inherited()
     51{
     52    Locale icuLocale(fLanguage.Code());
     53    UErrorCode icuStatus = U_ZERO_ERROR;
     54
     55    fFormatter = new RelativeDateTimeFormatter(icuLocale, icuStatus);
     56    if (fFormatter == NULL) {
     57        fInitStatus = B_NO_MEMORY;
     58        return;
     59    }
     60
     61    fCalendar = new GregorianCalendar(icuStatus);
     62    if (fCalendar == NULL) {
     63        fInitStatus = B_NO_MEMORY;
     64        return;
     65    }
     66
     67    if (!U_SUCCESS(icuStatus))
     68        fInitStatus = B_ERROR;
     69}
     70
     71
     72BRelativeDateTimeFormat::BRelativeDateTimeFormat(const BLanguage& language,
     73    const BFormattingConventions& conventions)
     74    : Inherited(language, conventions)
     75{
     76    Locale icuLocale(fLanguage.Code());
     77    UErrorCode icuStatus = U_ZERO_ERROR;
     78
     79    fFormatter = new RelativeDateTimeFormatter(icuLocale, icuStatus);
     80    if (fFormatter == NULL) {
     81        fInitStatus = B_NO_MEMORY;
     82        return;
     83    }
     84
     85    fCalendar = new GregorianCalendar(icuStatus);
     86    if (fCalendar == NULL) {
     87        fInitStatus = B_NO_MEMORY;
     88        return;
     89    }
     90
     91    if (!U_SUCCESS(icuStatus))
     92        fInitStatus = B_ERROR;
     93}
     94
     95
     96BRelativeDateTimeFormat::BRelativeDateTimeFormat(const BRelativeDateTimeFormat& other)
     97    : Inherited(other),
     98    fFormatter(other.fFormatter != NULL
     99        ? new RelativeDateTimeFormatter(*other.fFormatter) : NULL),
     100    fCalendar(other.fCalendar != NULL
     101        ? new GregorianCalendar(*other.fCalendar) : NULL)
     102{
     103    if ((fFormatter == NULL && other.fFormatter != NULL)
     104        || (fCalendar == NULL && other.fCalendar != NULL))
     105        fInitStatus = B_NO_MEMORY;
     106}
     107
     108
     109BRelativeDateTimeFormat::~BRelativeDateTimeFormat()
     110{
     111    delete fFormatter;
     112    delete fCalendar;
     113}
     114
     115
     116status_t
     117BRelativeDateTimeFormat::Format(BString& string,
     118    const time_t timeValue) const
     119{
     120    if (fFormatter == NULL)
     121        return B_NO_INIT;
     122
     123    time_t currentTime = time(NULL);
     124
     125    UErrorCode icuStatus = U_ZERO_ERROR;
     126    fCalendar->setTime((UDate)currentTime * 1000, icuStatus);
     127    if (!U_SUCCESS(icuStatus))
     128        return B_ERROR;
     129
     130    UDate UTimeValue = (UDate)timeValue * 1000;
     131
     132    int delta = 0;
     133    int offset = 1;
     134    URelativeDateTimeUnit unit = UDAT_REL_UNIT_SECOND;
     135
     136    for (int timeUnit = 0; timeUnit <= B_TIME_UNIT_LAST; ++timeUnit) {
     137        delta = fCalendar->fieldDifference(UTimeValue,
     138            kTimeUnitToICUDateField[timeUnit], icuStatus);
     139
     140        if (!U_SUCCESS(icuStatus))
     141            return B_ERROR;
     142
     143        if (abs(delta) >= offset) {
     144            unit = kTimeUnitToRelativeDateTime[timeUnit];
     145            break;
     146        }
     147    }
     148
     149    UnicodeString unicodeResult;
     150
     151    // Note: icu::RelativeDateTimeFormatter::formatNumeric() is a part of ICU Draft API
     152    // and may be changed in the future versions and was introduced in ICU 57.
     153    fFormatter->formatNumeric(delta, unit, unicodeResult, icuStatus);
     154
     155    if (!U_SUCCESS(icuStatus))
     156        return B_ERROR;
     157
     158    BStringByteSink byteSink(&string);
     159    unicodeResult.toUTF8(byteSink);
     160
     161    return B_OK;
     162}