xref: /haiku/src/kits/locale/DurationFormat.cpp (revision e0bc2fcce4c5ceb7b57d978b752cda01639d0098)
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