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