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/calendar.h> 15 #include <unicode/tmunit.h> 16 #include <unicode/utypes.h> 17 18 #include <AutoDeleter.h> 19 #include <TimeUnitFormat.h> 20 21 22 using BPrivate::ObjectDeleter; 23 24 25 // maps our unit element to the corresponding ICU unit 26 static const UCalendarDateFields skUnitMap[] = { 27 UCAL_YEAR, 28 UCAL_MONTH, 29 UCAL_WEEK_OF_MONTH, 30 UCAL_DAY_OF_WEEK, 31 UCAL_HOUR_OF_DAY, 32 UCAL_MINUTE, 33 UCAL_SECOND, 34 }; 35 36 37 status_t BDurationFormat::Format(bigtime_t startValue, bigtime_t stopValue, 38 BString* buffer, time_unit_style style, const BString& separator) const 39 { 40 if (buffer == NULL) 41 return B_BAD_VALUE; 42 43 UErrorCode icuStatus = U_ZERO_ERROR; 44 ObjectDeleter<Calendar> calendar = Calendar::createInstance(icuStatus); 45 if (calendar.Get() == NULL) 46 return B_NO_MEMORY; 47 if (!U_SUCCESS(icuStatus)) 48 return B_ERROR; 49 50 calendar->setTime((UDate)startValue / 1000, icuStatus); 51 if (!U_SUCCESS(icuStatus)) 52 return B_ERROR; 53 54 BTimeUnitFormat timeUnitFormat; 55 UDate stop = (UDate)stopValue / 1000; 56 bool needSeparator = false; 57 for (int unit = 0; unit <= B_TIME_UNIT_LAST; ++unit) { 58 int delta = calendar->fieldDifference(stop, skUnitMap[unit], icuStatus); 59 if (!U_SUCCESS(icuStatus)) 60 return B_ERROR; 61 62 if (delta != 0) { 63 if (needSeparator) 64 buffer->Append(separator); 65 else 66 needSeparator = true; 67 status_t status = timeUnitFormat.Format(delta, 68 (time_unit_element)unit, buffer, style); 69 if (status != B_OK) 70 return status; 71 } 72 } 73 74 return B_OK; 75 } 76