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