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