1 /* 2 * Copyright 2010-2014, 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 #include <unicode/uversion.h> 10 #include <DateTimeFormat.h> 11 12 #include <AutoDeleter.h> 13 #include <Autolock.h> 14 #include <FormattingConventionsPrivate.h> 15 #include <LanguagePrivate.h> 16 #include <TimeZone.h> 17 18 #include <ICUWrapper.h> 19 20 #include <unicode/datefmt.h> 21 #include <unicode/dtptngen.h> 22 #include <unicode/smpdtfmt.h> 23 24 25 BDateTimeFormat::BDateTimeFormat(const BLocale* locale) 26 : BFormat(locale) 27 { 28 } 29 30 31 BDateTimeFormat::BDateTimeFormat(const BLanguage& language, 32 const BFormattingConventions& conventions) 33 : BFormat(language, conventions) 34 { 35 } 36 37 38 BDateTimeFormat::BDateTimeFormat(const BDateTimeFormat &other) 39 : BFormat(other) 40 { 41 } 42 43 44 BDateTimeFormat::~BDateTimeFormat() 45 { 46 } 47 48 49 void 50 BDateTimeFormat::SetDateTimeFormat(BDateFormatStyle dateStyle, 51 BTimeFormatStyle timeStyle, int32 elements) { 52 UErrorCode error = U_ZERO_ERROR; 53 DateTimePatternGenerator* generator 54 = DateTimePatternGenerator::createInstance( 55 *BLanguage::Private(&fLanguage).ICULocale(), error); 56 57 BString skeleton; 58 if (elements & B_DATE_ELEMENT_YEAR) 59 skeleton << "yyyy"; 60 if (elements & B_DATE_ELEMENT_MONTH) 61 skeleton << "MM"; 62 if (elements & B_DATE_ELEMENT_WEEKDAY) 63 skeleton << "eee"; 64 if (elements & B_DATE_ELEMENT_DAY) 65 skeleton << "dd"; 66 if (elements & B_DATE_ELEMENT_AM_PM) 67 skeleton << "a"; 68 if (elements & B_DATE_ELEMENT_HOUR) { 69 if (fConventions.Use24HourClock()) 70 skeleton << "k"; 71 else 72 skeleton << "K"; 73 } 74 if (elements & B_DATE_ELEMENT_MINUTE) 75 skeleton << "mm"; 76 if (elements & B_DATE_ELEMENT_SECOND) 77 skeleton << "ss"; 78 if (elements & B_DATE_ELEMENT_TIMEZONE) 79 skeleton << "z"; 80 81 UnicodeString pattern = generator->getBestPattern( 82 UnicodeString::fromUTF8(skeleton.String()), error); 83 84 BString buffer; 85 BStringByteSink stringConverter(&buffer); 86 pattern.toUTF8(stringConverter); 87 88 fConventions.SetExplicitDateTimeFormat(dateStyle, timeStyle, buffer); 89 90 delete generator; 91 } 92 93 94 // #pragma mark - Formatting 95 96 97 ssize_t 98 BDateTimeFormat::Format(char* target, size_t maxSize, time_t time, 99 BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle) const 100 { 101 BString format; 102 fConventions.GetDateTimeFormat(dateStyle, timeStyle, format); 103 ObjectDeleter<DateFormat> dateFormatter(_CreateDateTimeFormatter(format)); 104 if (dateFormatter.Get() == NULL) 105 return B_NO_MEMORY; 106 107 UnicodeString icuString; 108 dateFormatter->format((UDate)time * 1000, icuString); 109 110 CheckedArrayByteSink stringConverter(target, maxSize); 111 icuString.toUTF8(stringConverter); 112 113 if (stringConverter.Overflowed()) 114 return B_BAD_VALUE; 115 116 return stringConverter.NumberOfBytesWritten(); 117 } 118 119 120 status_t 121 BDateTimeFormat::Format(BString& target, const time_t time, 122 BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle, 123 const BTimeZone* timeZone) const 124 { 125 BString format; 126 fConventions.GetDateTimeFormat(dateStyle, timeStyle, format); 127 ObjectDeleter<DateFormat> dateFormatter(_CreateDateTimeFormatter(format)); 128 if (dateFormatter.Get() == NULL) 129 return B_NO_MEMORY; 130 131 if (timeZone != NULL) { 132 ObjectDeleter<TimeZone> icuTimeZone( 133 TimeZone::createTimeZone(timeZone->ID().String())); 134 if (icuTimeZone.Get() == NULL) 135 return B_NO_MEMORY; 136 dateFormatter->setTimeZone(*icuTimeZone.Get()); 137 } 138 139 UnicodeString icuString; 140 dateFormatter->format((UDate)time * 1000, icuString); 141 142 target.Truncate(0); 143 BStringByteSink stringConverter(&target); 144 icuString.toUTF8(stringConverter); 145 146 return B_OK; 147 } 148 149 150 DateFormat* 151 BDateTimeFormat::_CreateDateTimeFormatter(const BString& format) const 152 { 153 Locale* icuLocale 154 = fConventions.UseStringsFromPreferredLanguage() 155 ? BLanguage::Private(&fLanguage).ICULocale() 156 : BFormattingConventions::Private(&fConventions).ICULocale(); 157 158 icu::DateFormat* dateFormatter = icu::DateFormat::createDateTimeInstance( 159 DateFormat::kDefault, DateFormat::kDefault, *icuLocale); 160 if (dateFormatter == NULL) 161 return NULL; 162 163 SimpleDateFormat* dateFormatterImpl 164 = static_cast<SimpleDateFormat*>(dateFormatter); 165 166 UnicodeString pattern(format.String()); 167 dateFormatterImpl->applyPattern(pattern); 168 169 return dateFormatter; 170 } 171