1/* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Oliver Tappe <zooey@hirschkaefer.de> 7 */ 8 9 10#include <unicode/uversion.h> 11#include <DurationFormat.h> 12 13#include <new> 14 15#include <unicode/gregocal.h> 16#include <unicode/utypes.h> 17 18#include <Locale.h> 19#include <LocaleRoster.h> 20#include <TimeZone.h> 21 22#include <TimeZonePrivate.h> 23 24 25U_NAMESPACE_USE 26 27 28// maps our unit element to the corresponding ICU unit 29static const UCalendarDateFields skUnitMap[] = { 30 UCAL_YEAR, 31 UCAL_MONTH, 32 UCAL_WEEK_OF_MONTH, 33 UCAL_DAY_OF_WEEK, 34 UCAL_HOUR_OF_DAY, 35 UCAL_MINUTE, 36 UCAL_SECOND, 37}; 38 39 40BDurationFormat::BDurationFormat(const BLanguage& language, 41 const BFormattingConventions& conventions, 42 const BString& separator, const time_unit_style style) 43 : 44 Inherited(language, conventions), 45 fSeparator(separator), 46 fTimeUnitFormat(language, conventions, style) 47{ 48 UErrorCode icuStatus = U_ZERO_ERROR; 49 fCalendar = new GregorianCalendar(icuStatus); 50 if (fCalendar == NULL) { 51 fInitStatus = B_NO_MEMORY; 52 return; 53 } 54} 55 56 57BDurationFormat::BDurationFormat(const BString& separator, 58 const time_unit_style style) 59 : 60 Inherited(), 61 fSeparator(separator), 62 fTimeUnitFormat(style) 63{ 64 UErrorCode icuStatus = U_ZERO_ERROR; 65 fCalendar = new GregorianCalendar(icuStatus); 66 if (fCalendar == NULL) { 67 fInitStatus = B_NO_MEMORY; 68 return; 69 } 70} 71 72 73BDurationFormat::BDurationFormat(const BDurationFormat& other) 74 : 75 Inherited(other), 76 fSeparator(other.fSeparator), 77 fTimeUnitFormat(other.fTimeUnitFormat), 78 fCalendar(other.fCalendar != NULL 79 ? new GregorianCalendar(*other.fCalendar) : NULL) 80{ 81 if (fCalendar == NULL && other.fCalendar != NULL) 82 fInitStatus = B_NO_MEMORY; 83} 84 85 86BDurationFormat::~BDurationFormat() 87{ 88 delete fCalendar; 89} 90 91 92void 93BDurationFormat::SetSeparator(const BString& separator) 94{ 95 fSeparator = separator; 96} 97 98 99status_t 100BDurationFormat::SetTimeZone(const BTimeZone* timeZone) 101{ 102 if (fCalendar == NULL) 103 return B_NO_INIT; 104 105 BTimeZone::Private zonePrivate; 106 if (timeZone == NULL) { 107 BTimeZone defaultTimeZone; 108 status_t result 109 = BLocaleRoster::Default()->GetDefaultTimeZone(&defaultTimeZone); 110 if (result != B_OK) 111 return result; 112 zonePrivate.SetTo(&defaultTimeZone); 113 } else 114 zonePrivate.SetTo(timeZone); 115 116 TimeZone* icuTimeZone = zonePrivate.ICUTimeZone(); 117 if (icuTimeZone != NULL) 118 fCalendar->setTimeZone(*icuTimeZone); 119 120 return B_OK; 121} 122 123 124status_t 125BDurationFormat::Format(BString& buffer, const bigtime_t startValue, 126 const bigtime_t stopValue) const 127{ 128 UErrorCode icuStatus = U_ZERO_ERROR; 129 fCalendar->setTime((UDate)startValue / 1000, icuStatus); 130 if (!U_SUCCESS(icuStatus)) 131 return B_ERROR; 132 133 UDate stop = (UDate)stopValue / 1000; 134 bool needSeparator = false; 135 for (int unit = 0; unit <= B_TIME_UNIT_LAST; ++unit) { 136 int delta 137 = fCalendar->fieldDifference(stop, skUnitMap[unit], icuStatus); 138 if (!U_SUCCESS(icuStatus)) 139 return B_ERROR; 140 141 if (delta != 0) { 142 if (needSeparator) 143 buffer.Append(fSeparator); 144 else 145 needSeparator = true; 146 status_t status = fTimeUnitFormat.Format(buffer, delta, 147 (time_unit_element)unit); 148 if (status != B_OK) 149 return status; 150 } 151 } 152 153 return B_OK; 154} 155