QT中时间时区处理总结

  最近项目中要做跨国设备时间校正功能,用到了时区时间,在此做一下记录。

目录

1.常见时区名

2.测试代码

3.运行效果


1.常见时区名

  "Pacific/Midway": "中途岛 (UTC-11:00)",                                                               
  "Pacific/Honolulu": "檀香山 (UTC-10:00)",
  "America/Anchorage": "安克雷奇 (UTC-08:00)",
  "America/Los_Angeles": "洛杉矶/美国太平洋 (UTC-07:00)",
  "America/Tijuana": "提华纳/美国太平洋 (UTC-07:00)",
  "America/Phoenix": "凤凰城美国山区 (UTC-07:00)",
  "America/Chihuahua": "奇瓦瓦 (UTC-06:00)",
  "America/Denver": "丹佛/美国山区 (UTC-06:00)",
  "America/Costa_Rica": "哥斯达黎加/美国中部 (UTC-06:00)",
  "America/Regina": "里贾纳/美国中部 (UTC-06:00)",
  "America/Mexico_City": "墨西哥城/美国中部 (UTC-05:00)",
  "America/Chicago": "芝加哥/美国中部 (UTC-05:00)",
  "America/Bogota": "波哥大/哥伦比亚 (UTC-05:00)",
  "America/New_York": "纽约/美国东部 (UTC-04:00)",
  "America/Caracas": "加拉加斯/委内瑞拉 (UTC-04:30)",
  "America/Barbados": "巴巴多斯/大西洋 (UTC-04:00)",
  "America/Manaus": "马瑙斯/亚马逊 (UTC-04:00)",
  "America/Santiago": "圣地亚哥 (UTC-03:00)",
  "America/Sao_Paulo": "圣保罗 (UTC-03:00)",
  "America/St_Johns": "圣约翰/纽芬兰 (UTC-04:00)",
  "America/Montevideo": "蒙得维的亚/乌拉圭 (UTC-03:00)",
  "America/Godthab": "戈特霍布 (UTC-02:00)",
  "Atlantic/South_Georgia": "南乔治亚 (UTC-02:00)",
  "Atlantic/Cape_Verde": "佛得角 (UTC-01:00)",
  "Atlantic/Azores": "亚述尔群岛 (UTC+00:00)",
  "Africa/Casablanca": "卡萨布兰卡 (UTC+00:00)",
  "Europe/London": "伦敦/格林尼治 (UTC+00:00)",
  "Africa/Brazzaville": "布拉扎维/西部非洲 (UTC+01:00)",
  "Africa/Windhoek": "温得和克 (UTC+01:00)",
  "Europe/Amsterdam": "阿姆斯特丹/中欧 (UTC+02:00)",
  "Europe/Belgrade": "贝尔格莱德/中欧 (UTC+02:00)",
  "Europe/Brussels": "布鲁塞尔/中欧 (UTC+02:00)",
  "Europe/Sarajevo": "萨拉热窝/中欧 (UTC+02:00)",
  "Africa/Harare": "哈拉雷/中部非洲 (UTC+02:00)",
  "Africa/Cairo": "开罗/东欧 (UTC+02:00)",
  "Asia/Beirut": "贝鲁特/东欧 (UTC+03:00)",
  "Europe/Athens": "雅典/东欧 (UTC+03:00)",
  "Europe/Helsinki": "赫尔辛基/东欧 (UTC+03:00)",
  "Asia/Jerusalem": "耶路撒冷/以色列 (UTC+03:00)",
  "Asia/Amman": "安曼/东欧 (UTC+03:00)",
  "Europe/Minsk": "明斯克 (UTC+03:00)",
  "Asia/Baghdad": "巴格达 (UTC+03:00)",
  "Europe/Moscow": "莫斯科 (UTC+03:00)",
  "Asia/Kuwait": "科威特 (UTC+03:00)",
  "Africa/Nairobi": "内罗毕/东部非洲 (UTC+03:00)",
  "Asia/Baku": "巴库 (UTC+05:00)",
  "Asia/Tbilisi": "第比利斯 (UTC+04:00)",
  "Asia/Yerevan": "埃里温 (UTC+04:00)",
  "Asia/Dubai": "迪拜 (UTC+04:00)",
  "Asia/Tehran": "德黑兰/伊朗 (UTC+04:30)",
  "Asia/Kabul": "喀布尔/阿富汗 (UTC+04:30)",
  "Asia/Karachi": "卡拉奇 (UTC+05:00)",
  "Asia/Oral": "乌拉尔 (UTC+05:00)",
  "Asia/Yekaterinburg": "叶卡捷林堡 (UTC+05:00)",
  "Asia/Colombo": "科伦坡 (UTC+05:30)",
  "Asia/Almaty": "阿拉木图 (UTC+06:00)",
  "Asia/Krasnoyarsk": "克拉斯诺亚尔斯克 (UTC+07:00)",
  "Asia/Bangkok": "曼谷 (UTC+07:00)",
  "Asia/Shanghai": "北京/中国 (UTC+08:00)",
  "Asia/Hong_Kong": "香港/中国 (UTC+08:00)",
  "Asia/Irkutsk": "伊尔库茨克 (UTC+08:00)",
  "Asia/Kuala_Lumpur": "吉隆坡 (UTC+08:00)",
  "Australia/Perth": "佩思 (UTC+08:00)",
  "Asia/Taipei": "台北时间 (UTC+08:00)",
  "Asia/Seoul": "首尔 (UTC+09:00)",
  "Asia/Tokyo": "东京/日本 (UTC+09:00)",
  "Asia/Yakutsk": "雅库茨克 (UTC+09:00)",
  "Australia/Adelaide": "阿德莱德 (UTC+09:30)",
  "Australia/Darwin": "达尔文 (UTC+09:30)",
  "Australia/Brisbane": "布里斯班 (UTC+10:00)",
  "Australia/Hobart": "霍巴特 (UTC+10:00)",
  "Australia/Sydney": "悉尼 (UTC+10:00)",
  "Asia/Vladivostok": "符拉迪沃斯托克/海参崴 (UTC+10:00)",
  "Pacific/Guam": "关岛 (UTC+10:00)",
  "Asia/Magadan": "马加丹 (UTC+10:00)",
  "Pacific/Majuro": "马朱罗 (UTC+12:00)",
  "Pacific/Auckland": "奥克兰 (UTC+12:00)",
  "Pacific/Fiji": "斐济 (UTC+12:00)",
  "Pacific/Tongatapu": "东加塔布 (UTC+13:00)",
  "America/Halifax": "哈利法克斯 (GMT-03:00)",
  "Asia/Jakarta": "雅加达 (GMT+07:00)",
  "America/Argentina/Buenos_Aires": "布宜诺斯艾利斯 (UTC-03:00)",
  "Asia/Kolkata": "亚洲/加尔各答 (GMT+05:30)",
  "Asia/Kathmandu": "加德满都 (GMT+05:45)",
  "Asia/Yangon": "仰光(GMT+06:30)",
  "Pacific/Noumea": "努美亚 (GMT+11:00)",
  "Etc/UTC": "Etc/UTC (GMT+00:00)",
  "America/Recife": "累西腓 (GMT-03:00)",
  "Europe/Madrid": "马德里 (GMT+01:00)",
  "Europe/Istanbul": "伊斯坦布尔 (GMT+03:00)"

2.测试代码

#include <QCoreApplication>
#include <QDateTime>
#include <QTimezone>


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 获取当前时间
    QDateTime curDateTime = QDateTime :: currentDateTime();
    qDebug() << curDateTime.toString("yyyy-MM-dd")
             << curDateTime.toString("yyyy-MM-dd hh:mm:ss")
             << curDateTime.toString("hh:mm:ss");

    // 使用指定日期和时间创建
    QDateTime customDateTime(QDate(2023, 12, 8), QTime(22, 56, 0));
     qDebug() << customDateTime.toString("yyyy-MM-dd hh:mm:ss");

     // 从QDateTime中分别得到QDate和QTime
     QDate date = curDateTime.date();
     QTime ctime = curDateTime.time();

     curDateTime.setDate(QDate(2023, 12, 9));
     curDateTime.setTime(QTime(23, 30, 0));
    qDebug() << curDateTime.toString("yyyy-MM-dd hh:mm:ss");
    qDebug() << curDateTime.toString(Qt::ISODate);

    // 根据当前日期时间获取特定时区的当前日期时间
    QDateTime tokyoDateTime = QDateTime::currentDateTime().toTimeZone(QTimeZone("Asia/Tokyo"));
    qDebug() << tokyoDateTime.toString("yyyy-MM-dd hh:mm:ss");

    // 字符串日期到时间
    QString strDateTime = "2013-12-08 23:17:50";
    qDebug() << "str datetime to datetime "
             << QDateTime::fromString(strDateTime, "yyyy-MM-dd hh:mm:ss").toString("yyyy-MM-dd hh:mm:ss");

    // 枚举时区
    /*
    int size = QTimeZone::availableTimeZoneIds().size();
    for (int i = 0; i < size; i++) {
        qDebug() << QTimeZone::availableTimeZoneIds().at(i);
    }
    */

    // 当前时间转UTC时间戳,秒,毫秒
    quint64 msecons = QDateTime::currentDateTime().toMSecsSinceEpoch();
    qDebug() << msecons;
    qDebug() << QDateTime::currentDateTime().toUTC().toMSecsSinceEpoch();
    qDebug() << QDateTime::currentDateTimeUtc().toMSecsSinceEpoch();

    qDebug() << QDateTime::currentDateTime().toSecsSinceEpoch()
             << QDateTime::currentDateTime().toUTC().toSecsSinceEpoch();
    // 根据毫秒时间戳恢复到当前时时间
    qDebug() << QDateTime::fromMSecsSinceEpoch(msecons, Qt::LocalTime).toString("yyyy-MM-dd hh:mm:ss");

    // 不管那个时区,UTC时间戳都是一样的
    qDebug() << QDateTime::currentDateTime().toTimeZone(QTimeZone("Asia/Tokyo")).toMSecsSinceEpoch()
             <<  QDateTime::currentDateTime().toMSecsSinceEpoch();

    // 指定时区得到时间
    qDebug() << QDateTime::fromMSecsSinceEpoch(QDateTime::currentDateTime().toTimeZone(QTimeZone("Asia/Tokyo")).toMSecsSinceEpoch(),
                                               QTimeZone("Asia/Tokyo")).toString("yyyy-MM-dd hh:mm:ss");


    return a.exec();
}

3.运行效果

unit uTimeZonesMgr; interface uses Windows, SysUtils, Classes, Registry, DateUtils; type {* 用于读取时区注册表TZI(长度为44)的属性值,存储时区信息 *} PRegTZIInfo = ^TRegTZIInfo; TRegTZIInfo = record Bias: Longint; StandardBias: Longint; DaylightBias: Longint; StandardDate: TSystemTime; DaylightDate: TSystemTime; end; {* 单个时区管理对象 *} TTimeZone = class private FTimeZoneName: string; //时区的显示名 FDisplay: string; //夏令时的名字 FDlt: string; //时区标准名字 FStd: string; //是Time zone information的缩写,描述时区的一些重要信息 FTZI: PRegTZIInfo; function GetSelfTimeZoneInformation: TTimeZoneInformation; public constructor Create; destructor Destroy; override; function UTCToLocalDateTime(const AUTC: TDateTime; var ALocalDateTime: TDateTime): Boolean; function LocalDateTimeToUTC(const ALocalDateTime: TDateTime; var AUTC: TDateTime): Boolean; public property TimeZoneName: string read FTimeZoneName write FTimeZoneName; property Display: string read FDisplay write FDisplay; property Dlt: string read FDlt write FDlt; property Std: string read FStd write FStd; property TZI: PRegTZIInfo read FTZI write FTZI; end; {* 所有时区管理对象 *} TTimeZones = class private FTimeZoneKeyPath: string; FTimeZoneList: TStringList; FDefaultTimeZone: TTimeZone; procedure CollectTimeZone; procedure DestoryTimeZones; procedure CheckISDefaultTimeZone(ATimeZone: TTimeZone); public constructor Create; destructor Destroy; override; function FindTimeZone(const ADisplay: string): TTimeZone; public property TimeZoneList: TStringList read FTimeZoneList; property DefaultTimeZone: TTimeZone read FDefaultTimeZone; end; implementation { TTimeZones } procedure TTimeZones.CheckISDefaultTimeZone(ATimeZone: TTimeZone); var DefaultTimeZone: TTimeZoneInformation; begin GetTimeZoneInformation(DefaultTimeZone); if (ATimeZone.TZI.Bias = DefaultTimeZone.Bias) and (ATimeZone.Std = DefaultTimeZone.StandardName) then FDefaultTimeZone := ATimeZone; end; procedure TTimeZones.CollectTimeZone; var reg, tempReg: TRegistry; tempKeyPath: string; tempTimeZoneStrings: TStrings; iCir: Integer; tempTimeZone: TTimeZone; begin reg := TRegistry.Create; try reg.RootKey := HKEY_LOCAL_MACHINE; reg.OpenKey(FTimeZoneKeyPath, False); tempTimeZoneStrings := TStringList.Create; try reg.GetKeyNames(tempTimeZoneStrings); for iCir := 0 to tempTimeZoneStrings.Count - 1 do begin tempKeyPath := FTimeZoneKeyPath + '\' + tempTimeZoneStrings.Strings[iCir]; tempReg := TRegistry.Create; try tempReg.RootKey := HKEY_LOCAL_MACHINE; tempReg.OpenKey(tempKeyPath, False); tempTimeZone := TTimeZone.Create; tempTimeZone.TimeZoneName := tempTimeZoneStrings.Strings[iCir]; tempTimeZone.Display := tempReg.ReadString('Display'); tempTimeZone.Std := tempReg.ReadString('Std'); tempTimeZone.Dlt := tempReg.ReadString('Dlt'); tempReg.ReadBinaryData('TZI', tempTimeZone.TZI^, SizeOf(TRegTZIInfo)); FTimeZoneList.AddObject(tempTimeZone.Display, tempTimeZone); if FDefaultTimeZone = nil then CheckISDefaultTimeZone(tempTimeZone); finally tempReg.CloseKey; tempReg.Free; end; end; finally tempTimeZoneStrings.Free; end; finally reg.CloseKey; reg.Free; end; end; constructor TTimeZones.Create; begin FTimeZoneKeyPath := '\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones'; FTimeZoneList := TStringList.Create; FTimeZoneList.Sorted := True; FDefaultTimeZone := nil; CollectTimeZone; end; procedure TTimeZones.DestoryTimeZones; var iCir: Integer; tempTimeZone: TTimeZone; begin for iCir := 0 to FTimeZoneList.Count - 1 do begin tempTimeZone := TTimeZone(FTimeZoneList.Objects[iCir]); tempTimeZone.Free; end; FTimeZoneList.Clear; FTimeZoneList.Free; end; destructor TTimeZones.Destroy; begin DestoryTimeZones(); inherited; end; function TTimeZones.FindTimeZone(const ADisplay: string): TTimeZone; var iIndex: Integer; begin Result := nil; FTimeZoneList.Sort; if FTimeZoneList.Find(ADisplay, iIndex) then begin Result := TTimeZone(FTimeZoneList.Objects[iIndex]); end; end; { TTimeZone } constructor TTimeZone.Create; begin FTZI := GetMemory(SizeOf(TRegTZIInfo)); FillMemory(FTZI, SizeOf(TRegTZIInfo), 0); end; destructor TTimeZone.Destroy; begin FreeMemory(FTZI); inherited; end; function TTimeZone.GetSelfTimeZoneInformation: TTimeZoneInformation; begin GetTimeZoneInformation(Result); Result.Bias := TZI^.Bias; Result.StandardBias := TZI^.StandardBias; Result.StandardDate := TZI^.StandardDate; Result.DaylightBias := TZI^.DaylightBias; Result.DaylightDate := TZI^.DaylightDate; end; function TTimeZone.LocalDateTimeToUTC(const ALocalDateTime: TDateTime; var AUTC: TDateTime): Boolean; var tempLocalToLocal: TDateTime; iMilliSecond: Int64; begin Result := UTCToLocalDateTime(ALocalDateTime, tempLocalToLocal); if Result then begin if tempLocalToLocal > ALocalDateTime then begin iMilliSecond := MilliSecondsBetween(tempLocalToLocal, ALocalDateTime); AUTC := IncMilliSecond(ALocalDateTime, iMilliSecond * -1); end else begin iMilliSecond := MilliSecondsBetween(ALocalDateTime, tempLocalToLocal); AUTC := IncMilliSecond(ALocalDateTime, iMilliSecond); end; Result := True; end; end; function TTimeZone.UTCToLocalDateTime(const AUTC: TDateTime; var ALocalDateTime: TDateTime): Boolean; var TimeZone: TTimeZoneInformation; stUTC, stLC: SYSTEMTIME; begin Result := False; TimeZone := GetSelfTimeZoneInformation; DateTimeToSystemTime(AUTC, stUTC); if SystemTimeToTzSpecificLocalTime(@TimeZone, stUTC, stLC) then begin ALocalDateTime := SystemTimeToDateTime(stLC); Result := True; end; end; end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值