目录
一、项目背景
在停车收费软件在海外应用中对于不同的国家,收费金额、过车时间等等虽然可以按照统一格式进行存储,但是界面展示等需要遵循当地习俗,不同国家地区习俗不同,如货币符号,数字分割符号,数字分割格式,时间展示方式等,此时QLocale模块可以根据不同国家给出合理的显示方式。
二、QLocale基本介绍
QLocale是 Qt 框架中用于实现国际化和本地化的核心类,它定义了用户所在区域的特定文化规则,确保应用程序能以符合用户习惯的方式展示数字、日期、货币等信息,以下是货币和时间等本地化代码。
三、实际使用举例
继承QSharedData提升数据效率
class LocalManagerData : public QSharedData {
public:
QLocale locale;
LocalManagerData(const QLocale &loc)
: locale(loc) {}
};
LocalManager 单例便于集成到项目
class LocalManager {
public:
enum Country {
UnitedStates,
China,
Japan,
Germany,
France,
UnitedKingdom,
SouthKorea,
Canada,
Australia,
Russia,
Vietnam
// 添加更多国家...
};
//枚举时间格式
enum DateTimeFormat {
LongDate,
LongTime,
ShortTime,
BaseTime1,//"yyyy-MM-ddTHH:mm:ss"
BaseTime2,// "yyyy-MM-dd HH:mm:ss"
BaseTime3,//"yyyyMMddHHmmss"
BaseTime4,//"yyyy-MM-dd-HH-mm-ss"
BaseTime5,//"HH:ss"
BaseTime6,//"yyyyMMddHHmmsszzz"
BaseTime7,//"HH:mm"
BaseTime8,//"yyyy/MM/dd HH:mm:ss"
BaseTime9 //"HH:mm:ss"
};
static LocalManager* instance()
{
static LocalManager instance;
return &instance;
}
//根据locate获取时区
QString getTimeZoneIdForLocale(const QLocale &locale)
{
switch (locale.country()) {
case QLocale::China:
return "Asia/Shanghai";
case QLocale::UnitedStates:
return "America/New_York"; // 东部时间作为美国代表
case QLocale::Germany:
return "Europe/Berlin";
case QLocale::Japan:
return "Asia/Tokyo";
case QLocale::UnitedKingdom:
return "Europe/London";
case QLocale::France:
return "Europe/Paris";
case QLocale::Canada:
return "America/Toronto";
case QLocale::Australia:
return "Australia/Sydney";
case QLocale::Vietnam:
return "Asia/Ho_Chi_Minh";
case QLocale::Russia:
return "Europe/Moscow";
default:
// 如果无法识别,则回落到系统时区
return QTimeZone::systemTimeZone().id();
}
}
// 切换国家(自动匹配语言和货币)
void switchCountry(Country country) {
QMutexLocker locker(&m_mutex);
static const QHash<Country, QLocale> localeMap = {
{ UnitedStates, QLocale(QLocale::English, QLocale::UnitedStates) },
{ China, QLocale(QLocale::Chinese, QLocale::China) },
{ Japan, QLocale(QLocale::Japanese, QLocale::Japan) },
{ Germany, QLocale(QLocale::German, QLocale::Germany) },
{ France, QLocale(QLocale::French, QLocale::France) },
{ UnitedKingdom, QLocale(QLocale::English, QLocale::UnitedKingdom) },
{ SouthKorea, QLocale(QLocale::Korean, QLocale::SouthKorea) },
{ Canada, QLocale(QLocale::English, QLocale::Canada) },
{ Australia, QLocale(QLocale::English, QLocale::Australia) },
{ Russia, QLocale(QLocale::Russian, QLocale::Russia) },
{ Vietnam, QLocale(QLocale::Vietnamese, QLocale::Vietnam) }
};
auto it = localeMap.find(country);
d->locale = (it != localeMap.end()) ? it.value() : QLocale::system();
}
// 格式化价格
QString formatPrice(qreal price, int precision = 2) const {
if (std::isnan(price) || std::isinf(price))
return QObject::tr("Invalid amount");
QMutexLocker locker(&m_mutex);
QString amount = QString::number(price, 'f', precision); // 强制保留precision位小数
return d->locale.toCurrencyString(amount.toDouble());
}
//格式化时间
QString formatDateTime(const QDateTime& dt, DateTimeFormat type = DateTimeFormat::LongDate) {
if (type >= DateTimeFormat::LongDate && type <= DateTimeFormat::BaseTime9)
{
switch (type)
{
case DateTimeFormat::LongDate:
return d->locale.toString(dt.date(), QLocale::LongFormat);
case DateTimeFormat::LongTime:
return d->locale.toString(dt.time(), QLocale::LongFormat);
case DateTimeFormat::ShortTime:
return d->locale.toString(dt.time(), QLocale::ShortFormat);
case DateTimeFormat::BaseTime1:
return d->locale.toString(dt, "yyyy-MM-ddTHH:mm:ss");
case DateTimeFormat::BaseTime2:
return d->locale.toString(dt, "yyyy-MM-dd HH:mm:ss");
case DateTimeFormat::BaseTime3:
return d->locale.toString(dt, "yyyyMMddHHmmss");
case DateTimeFormat::BaseTime4:
return d->locale.toString(dt, "yyyy-MM-dd-HH-mm-ss");
case DateTimeFormat::BaseTime5:
return d->locale.toString(dt, "HH:ss");
case DateTimeFormat::BaseTime6:
return d->locale.toString(dt, "yyyyMMddHHmmsszzz");
case DateTimeFormat::BaseTime7:
return d->locale.toString(dt, "HH:mm");
case DateTimeFormat::BaseTime8:
return d->locale.toString(dt, "yyyy/MM/dd HH:mm:ss");
case DateTimeFormat::BaseTime9:
return d->locale.toString(dt, "HH:mm:ss");
}
}
return "";
}
QString formatToLocalDisplay(const QString &isoTime, DateTimeFormat type = DateTimeFormat::LongDate) {
// 解析 ISO 时间(移除末尾的 'Z' 并解析为 UTC)
QString cleanIso = isoTime;
if (cleanIso.endsWith('Z') || cleanIso.endsWith('z')) {
cleanIso.chop(1);
}
QDateTime utcTime = QDateTime::fromString(cleanIso, Qt::ISODate);
utcTime.setTimeZone(QTimeZone("UTC"));
if (!utcTime.isValid()) {
return isoTime; // 返回原始字符串作为 fallback
}
QString tzId = getTimeZoneIdForLocale(d->locale);
QTimeZone targetZone(tzId.toUtf8());
if (!targetZone.isValid()) {
targetZone = QTimeZone::systemTimeZone(); // 回退
}
// 设置目标时区
QDateTime localizedLocalTime = utcTime.toTimeZone(targetZone);
return formatDateTime(localizedLocalTime, type);
}
// 获取当前系统本地化的日期时间
QString currentDateLocalTime(const QString& format = "yyyy-MM-dd HH:mm:ss") {
QString tzId = getTimeZoneIdForLocale(d->locale);
QTimeZone targetZone(tzId.toUtf8());
if (!targetZone.isValid()) {
targetZone = QTimeZone::systemTimeZone();
}
// 设置目标时区
QDateTime localizedLocalTime = QDateTime::currentDateTime().toTimeZone(targetZone);
return d->locale.toString(localizedLocalTime, format);
}
//获取当前的UTC时间
QString currentUtcIsoTime() {
return QDateTime::currentDateTimeUtc().toString(Qt::ISODate) + "Z";
}
// 获取当前货币代码(如 USD, CNY)
QString currencyCode() const {
QMutexLocker locker(&m_mutex);
return d->locale.currencySymbol(QLocale::CurrencyIsoCode);
}
// 获取当前国家名称(本地化)
QString countryName() const {
QMutexLocker locker(&m_mutex);
return d->locale.countryToString(d->locale.country());
}
// 获取语言名称
QString languageName() const {
QMutexLocker locker(&m_mutex);
return d->locale.languageToString(d->locale.language());
}
QLocale currentLocale() const {
QMutexLocker locker(&m_mutex);
return d->locale;
}
private:
explicit LocalManager()
: d(new LocalManagerData(QLocale::system())) {}
static LocalManager *m_instance;
QSharedDataPointer<LocalManagerData> d;
mutable QMutex m_mutex;
};
// 静态成员初始化
LocalManager* LocalManager::m_instance = nullptr;
使用举例
void Test()
{
auto *cm = LocalManager::instance();
cm->switchCountry(LocalManager::China);
qreal testPrice = qRound(5432108.45 * 100.0) / 100.0;
ui.label_rmb->setText(cm->formatPrice(testPrice));
ui.label_rmb_systime->setText(cm->currentDateLocalTime());
//ui.label_rmb_systime->setText(cm->formatDateTime(QDateTime::currentDateTime()));
cm->switchCountry(LocalManager::UnitedStates);
ui.label_us->setText(cm->formatPrice(testPrice));
ui.label_us_systime->setText(cm->currentDateLocalTime());
//ui.label_us_systime->setText(cm->formatDateTime(QDateTime::currentDateTime()));
cm->switchCountry(LocalManager::Russia);
ui.label_russia->setText(cm->formatPrice(testPrice));
ui.label_russia_systime->setText(cm->currentDateLocalTime());
//ui.label_russia_systime->setText(cm->formatDateTime(QDateTime::currentDateTime()));
cm->switchCountry(LocalManager::UnitedKingdom);
ui.label_uk->setText(cm->formatPrice(testPrice));
ui.label_uk_sysytime->setText(cm->currentDateLocalTime());
//ui.label_uk_sysytime->setText(cm->formatDateTime(QDateTime::currentDateTime()));
cm->switchCountry(LocalManager::Vietnam);
ui.label_yn->setText(cm->formatPrice(testPrice));
ui.label_yn_systime->setText(cm->currentDateLocalTime());
//ui.label_yn_systime->setText(cm->formatDateTime(QDateTime::currentDateTime()));
}
1251

被折叠的 条评论
为什么被折叠?



