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