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 50 51 BDurationFormat::BDurationFormat(const BDurationFormat& other) 52 : 53 Inherited(other), 54 fSeparator(other.fSeparator), 55 fTimeUnitFormat(other.fTimeUnitFormat), 56 fCalendar(other.fCalendar != NULL 57 ? new GregorianCalendar(*other.fCalendar) : NULL) 58 { 59 if (fCalendar == NULL && other.fCalendar != NULL) 60 fInitStatus = B_NO_MEMORY; 61 } 62 63 64 BDurationFormat::~BDurationFormat() 65 { 66 delete fCalendar; 67 } 68 69 70 BDurationFormat& 71 BDurationFormat::operator=(const BDurationFormat& other) 72 { 73 if (this == &other) 74 return *this; 75 76 fSeparator = other.fSeparator; 77 fTimeUnitFormat = other.fTimeUnitFormat; 78 delete fCalendar; 79 fCalendar = other.fCalendar != NULL 80 ? new GregorianCalendar(*other.fCalendar) : NULL; 81 82 if (fCalendar == NULL && other.fCalendar != NULL) 83 fInitStatus = B_NO_MEMORY; 84 85 return *this; 86 } 87 88 89 void 90 BDurationFormat::SetSeparator(const BString& separator) 91 { 92 fSeparator = separator; 93 } 94 95 96 status_t 97 BDurationFormat::SetLanguage(const BLanguage& language) 98 { 99 status_t result = Inherited::SetLanguage(language); 100 if (result != B_OK) 101 return result; 102 103 return fTimeUnitFormat.SetLanguage(language); 104 } 105 106 107 status_t 108 BDurationFormat::SetTimeZone(const BTimeZone* timeZone) 109 { 110 if (fCalendar == NULL) 111 return B_NO_INIT; 112 113 BTimeZone::Private zonePrivate; 114 if (timeZone == NULL) { 115 BTimeZone defaultTimeZone; 116 status_t result 117 = BLocaleRoster::Default()->GetDefaultTimeZone(&defaultTimeZone); 118 if (result != B_OK) 119 return result; 120 zonePrivate.SetTo(&defaultTimeZone); 121 } else 122 zonePrivate.SetTo(timeZone); 123 124 TimeZone* icuTimeZone = zonePrivate.ICUTimeZone(); 125 if (icuTimeZone != NULL) 126 fCalendar->setTimeZone(*icuTimeZone); 127 128 return B_OK; 129 } 130 131 132 status_t 133 BDurationFormat::Format(bigtime_t startValue, bigtime_t stopValue, 134 BString* buffer, time_unit_style style) const 135 { 136 if (buffer == NULL) 137 return B_BAD_VALUE; 138 139 UErrorCode icuStatus = U_ZERO_ERROR; 140 fCalendar->setTime((UDate)startValue / 1000, icuStatus); 141 if (!U_SUCCESS(icuStatus)) 142 return B_ERROR; 143 144 UDate stop = (UDate)stopValue / 1000; 145 bool needSeparator = false; 146 for (int unit = 0; unit <= B_TIME_UNIT_LAST; ++unit) { 147 int delta 148 = fCalendar->fieldDifference(stop, skUnitMap[unit], icuStatus); 149 if (!U_SUCCESS(icuStatus)) 150 return B_ERROR; 151 152 if (delta != 0) { 153 if (needSeparator) 154 buffer->Append(fSeparator); 155 else 156 needSeparator = true; 157 status_t status = fTimeUnitFormat.Format(delta, 158 (time_unit_element)unit, buffer, style); 159 if (status != B_OK) 160 return status; 161 } 162 } 163 164 return B_OK; 165 } 166