一、问题详情

  • 系统版本: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(&current);
    if (!std::isnan(hourWest_)) {
        current = current - int32_t(hourWest_ * TOTAL_SECONDS_OF_HOUR);
        timeZoneTime = std::gmtime(&current); // 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);
}
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐