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

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

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