4.1Release版本TextClock组件多语言时间格式化问题修复
·
一、问题详情
- 系统版本:OpenHarmony-v4.1-Release(注意是tag版本,代码修改以tag版本为准)
- 问题详情:使用TextClock组件显示当前系统时间,当使用i18n.System.setAppPreferredLanguage接口设置当前应用的语言偏好时,如果设置的不是中文、英文的情况下,日期和时间存在未格式化或者显示错误的情况,设置部分语言时还存在应用闪退的情况。
二、修改文件
foundation/arkui/ace_engine/frameworks/core/components_ng/pattern/text_clock/text_clock_pattern.cpp
1. 修改DEFAULT_FORMAT与FORM_FORMAT
将41、42两行
const std::string DEFAULT_FORMAT = "hms";
const std::string FORM_FORMAT = "hm";
替换成下面的内容
const std::string DEFAULT_FORMAT = "aa hh:mm:ss";
const std::string FORM_FORMAT = "hh:mm";
constexpr int32_t STRING_NEXT_POS = 1;
constexpr int32_t MAX_LENGTH_OF_MILLIS = 3;
constexpr int32_t SIZE_OF_AM_PM_STRING = 2;
constexpr int32_t SIZE_OF_TIME_TEXT = 30;
constexpr int32_t BOUNDARY_OF_AM_PM = 12;
const char CHAR_SPACE = ' ';
const std::string STR_PREFIX_24H = " 0";
const std::string STR_PREFIX_12H = " ";
const std::string DEFAULT_FORMAT_24H = "HH:mm:ss";
const std::string FORM_FORMAT_24H = "HH:mm";
const std::string FORMAT_12H = "%Y/%m/%d %I:%M:%S";
const std::string FORMAT_24H = "%Y/%m/%d %H:%M:%S";
2. 替换GetCurrentFormatDateTime方法
下面是修改后的TextClockPattern::GetCurrentFormatDateTime方法,可以对比修改,也可以替换
std::string TextClockPattern::GetCurrentFormatDateTime()
{
auto now = std::chrono::system_clock::now();
time_t current = std::chrono::system_clock::to_time_t(now);
auto* timeZoneTime = std::localtime(¤t);
if (!std::isnan(hourWest_)) {
current = current - int32_t(hourWest_ * TOTAL_SECONDS_OF_HOUR);
timeZoneTime = std::gmtime(¤t); // Convert to UTC time.
}
CHECK_NULL_RETURN(timeZoneTime, "");
DateTime dateTime; // This is for i18n date time.
dateTime.year = timeZoneTime->tm_year + BASE_YEAR;
dateTime.month = timeZoneTime->tm_mon;
dateTime.day = timeZoneTime->tm_mday;
dateTime.hour = timeZoneTime->tm_hour;
dateTime.minute = timeZoneTime->tm_min;
dateTime.second = timeZoneTime->tm_sec;
if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) && !isForm_) {
return Localization::GetInstance()->FormatDateTime(dateTime, GetFormat());
}
dateTime.week = timeZoneTime->tm_wday; // 0-6
// parse input format
formatElementMap.clear();
bool is24H = is24H_;
ParseInputFormat(is24H);
std::string dateTimeFormat = is24H ? FORMAT_24H : FORMAT_12H;
int32_t hour = timeZoneTime->tm_hour;
char buffer[SIZE_OF_TIME_TEXT] = {};
std::strftime(buffer, sizeof(buffer), dateTimeFormat.c_str(), timeZoneTime);
CHECK_NULL_RETURN(buffer, "");
auto duration_cast_to_millis = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
auto timeValue = duration_cast_to_millis.count();
auto millis = std::to_string(timeValue % 1000);
auto millisLength = millis.length();
if (millisLength < MAX_LENGTH_OF_MILLIS) {
millis = std::string(MAX_LENGTH_OF_MILLIS - millisLength, '0') + millis;
}
std::string dateTimeValue = std::string(buffer) + "." + millis;
std::string strAmPm = "";
if (!is24H) {
auto zeroPos = dateTimeValue.find(STR_PREFIX_24H);
if (zeroPos != std::string::npos) {
dateTimeValue = dateTimeValue.replace(zeroPos, STR_PREFIX_24H.length(), STR_PREFIX_12H);
}
std::vector<std::string> amPmStrings = Localization::GetInstance()->GetAmPmStrings();
if (amPmStrings.size() >= SIZE_OF_AM_PM_STRING) {
if (hour < BOUNDARY_OF_AM_PM) {
strAmPm = amPmStrings[0];
} else {
strAmPm = amPmStrings[1];
}
}
}
std::string tempdateTimeValue = dateTimeValue;
std::vector<std::string> curDateTime = ParseDateTimeValue(tempdateTimeValue);
auto spacePos = tempdateTimeValue.find(CHAR_SPACE);
if (spacePos != std::string::npos) {
tempdateTimeValue.insert(spacePos + STRING_NEXT_POS, strAmPm);
}
curDateTime[(int32_t)(TextClockElementIndex::CUR_AMPM_INDEX)] = strAmPm;
// parse week
curDateTime[(int32_t)(TextClockElementIndex::CUR_WEEK_INDEX)] = GetWeek(false, timeZoneTime->tm_wday);
curDateTime[(int32_t)(TextClockElementIndex::CUR_SHORT_WEEK_INDEX)] = GetWeek(true, timeZoneTime->tm_wday);
// splice date time
std::string outputDateTime = SpliceDateTime(curDateTime);
if ((curDateTime[(int32_t)(TextClockElementIndex::CUR_YEAR_INDEX)] == "1900") || (outputDateTime == "")) {
if (isForm_) {
TextClockFormatElement tempFormatElement;
std::vector<std::string> formSplitter = { "h", ":", "m" };
formatElementMap.clear();
tempFormatElement.formatElement = formSplitter[0];
tempFormatElement.elementKey = 'h';
tempFormatElement.formatElementNum = (int32_t)(TextClockElementIndex::CUR_HOUR_INDEX);
formatElementMap[0] = tempFormatElement;
tempFormatElement.formatElement = formSplitter[1];
tempFormatElement.elementKey = ':';
tempFormatElement.formatElementNum = (int32_t)(TextClockElementIndex::CUR_MAX_INDEX);
formatElementMap[1] = tempFormatElement;
tempFormatElement.formatElement = formSplitter[2];
tempFormatElement.elementKey = 'm';
tempFormatElement.formatElementNum = (int32_t)(TextClockElementIndex::CUR_MINUTE_INDEX);
formatElementMap[2] = tempFormatElement;
outputDateTime = SpliceDateTime(curDateTime);
} else {
outputDateTime = tempdateTimeValue;
}
}
return outputDateTime;
}
3. 修改ParseInputFormat
将TextClockPattern::ParseInputFormat函数的前四行内容
std::string inputFormat = (GetFormat() == DEFAULT_FORMAT) ? "aa h:m:s" : GetFormat();
if (inputFormat == FORM_FORMAT && isForm_) {
inputFormat = "h:m";
}
替换成
std::string inputFormat = GetFormat();
4. 替换GetFormat方法
下面是修改后的TextClockPattern::GetFormat,可以对比修改,也可以替换
std::string TextClockPattern::GetFormat() const
{
auto textClockLayoutProperty = GetLayoutProperty<TextClockLayoutProperty>();
if (isForm_) {
auto defaultFormFormat = FORM_FORMAT;
if (is24H_) {
defaultFormFormat = FORM_FORMAT_24H;
}
CHECK_NULL_RETURN(textClockLayoutProperty, defaultFormFormat);
std::string result = textClockLayoutProperty->GetFormat().value_or(defaultFormFormat);
if (result.find("s") != std::string::npos || result.find("S") != std::string::npos) {
return defaultFormFormat;
}
return result;
}
auto defaultFormat = DEFAULT_FORMAT;
if (is24H_) {
defaultFormat = DEFAULT_FORMAT_24H;
}
CHECK_NULL_RETURN(textClockLayoutProperty, defaultFormat);
return textClockLayoutProperty->GetFormat().value_or(defaultFormat);
}
更多推荐
所有评论(0)