本文档依据当前工程中的以下文件编写:
src/util/DateUtil.h文档以 .cpp 的实际实现为准,覆盖 DateUtil 的全部公开接口、时间单位、时区语义、真机与模拟器差异、错误边界和调用示例。
#include "util/DateUtil.h"
#include "util/StringUtil.h" // 使用本文中的格式化和校验示例时需要
#include "util/FileUtil.h" // 使用导出耗时示例时需要
#include <chrono>
#include <cstdint>
#include <iostream>
#include <string>
using stt::util::DateUtil;
using stt::util::FileUtil;
using stt::util::StringUtil;
DateUtil 的方法全部是静态方法,不需要创建对象:
int today = DateUtil::today();
uint64_t nowMs = DateUtil::getMsTimeStamp2();
不使用 using 时可以写完整名称:
std::string now = stt::util::DateUtil::getTimeString();
本类同时使用秒和毫秒,调用错误不会产生编译错误,但结果可能相差 1000 倍。
| 接口 | 单位 | 起点/含义 |
|---|---|---|
getMsTimeStamp() |
毫秒 | 从本次开机开始的单调时间 |
getMsTimeStamp2() |
毫秒 | 从 1970-01-01 00:00:00 UTC 开始 |
getMsTimeStamp2(...) |
毫秒 | 指定本地日期时间对应的 Unix 时间戳 |
getTimeStamp() |
秒 | 从 1970-01-01 00:00:00 UTC 开始 |
getUnixTime(...) |
秒 | 把给定字段按 UTC 解释后的 Unix 时间戳 |
toString(ms, ...) |
输入为毫秒 | 转为本地日期时间字符串 |
formatDate |
不在本类中 | StringUtil::formatDate 的输入是秒,不是毫秒 |
常见换算:
uint64_t nowMs = DateUtil::getMsTimeStamp2();
uint64_t nowSec = nowMs / 1000;
// StringUtil::formatDate 接收秒
std::string text = StringUtil::formatDate(nowMs / 1000);
getTimeString、today、getDate、parse、toString 使用本地时区。getUnixTime 使用 UTC 规则,不使用本地时区。getMsTimeStamp2 使用 mktime,把字段解释为本地时间。| 接口 | ARM 真机 | Windows 模拟器 |
|---|---|---|
setDateTime |
尝试写 RTC 和系统时间 | 不执行设置,仍直接返回 true |
setTimezone |
写配置并修改当前进程的 TZ |
空操作 |
getTimezone |
读取当前本地时间偏移 | 读取 Windows Bias |
getUnixTime |
使用 timegm |
使用 _mkgmtime |
不能仅根据模拟器上的 true 返回值判断系统时钟已经设置成功。
| 接口 | 当前实现行为 | 调用建议 |
|---|---|---|
getTimezone |
UTC+8 返回 -8,和头文件“东区为正”的说明相反 |
显示常规时区时取负值 |
getMonthMaxDay |
非法月份也返回 30 |
调用前限制月份为 1..12 |
getMsTimeStamp2(string) |
只检查长度为 19,不检查分隔符和日期是否合法 | 先严格校验格式与范围 |
parse |
不检查 std::get_time 是否解析失败 |
不要用它验证外部输入 |
setDateTime |
ARM 的 tm 没有整体清零,且不检查 settimeofday 结果 |
设置后必须重新读取并核对时间 |
setDateTime/setTimezone |
Windows 模拟器不执行实际设置 | 系统设置功能必须上真机测试 |
convert2HMS |
负秒数会产生异常文本 | 只传非负数 |
toString |
依赖全局数据库,格式串直接拼入 SQL | Runtime/DB 必须已初始化,格式不可来自不可信输入 |
| 分类 | 方法 | 主要用途 |
|---|---|---|
| 当前日期时间 | getDate、today、getTimeString |
读取本地日期时间 |
| 时间戳 | getMsTimeStamp、getMsTimeStamp2、getTimeStamp |
计时或记录绝对时刻 |
| 日期构造与运算 | getUnixTime、addDays、prevDay、nextDay |
构造 UTC 时间或按日运算 |
| 日历信息 | getWeekDay、getMonthMaxDay |
星期和月天数 |
| 系统设置 | setDateTime、getTimezone、setTimezone |
真机时间与时区设置 |
| 时长显示 | convert2HMS |
秒数转时分秒 |
| 解析与差值 | parse、diffInSeconds |
本地时间字符串解析和秒差 |
| 时间戳格式化 | toString |
毫秒时间戳转本地字符串 |
getDatestatic int getDate(string f);
读取系统当前本地时间的一个字段。
有效参数:
f |
返回内容 | 典型范围 |
|---|---|---|
"Y" |
年 | 例如 2026 |
"M" |
月 | 1..12 |
"D" |
日 | 1..31 |
"hh" |
小时 | 0..23 |
"mm" |
分钟 | 0..59 |
"ss" |
秒 | 0..60,极少数平台可能出现闰秒 |
示例:
int year = DateUtil::getDate("Y");
int month = DateUtil::getDate("M");
int day = DateUtil::getDate("D");
int hour = DateUtil::getDate("hh");
int minute = DateUtil::getDate("mm");
int second = DateUtil::getDate("ss");
构造 yyyyMMdd 文本:
std::string ymd = StringUtil::snprintf(
"%04d%02d%02d",
DateUtil::getDate("Y"),
DateUtil::getDate("M"),
DateUtil::getDate("D"));
注意事项:
"y"、"HH"、"month" 都是无效值。0,接口没有错误状态。getTimeString,需要日期整数时使用 today()。localtime 的静态缓冲区,不适合多个线程并发调用。todaystatic int today();
返回当前本地日期的 yyyyMMdd 整数:
int date = DateUtil::today();
// 例如 20261020
int year = date / 10000;
int month = date / 100 % 100;
int day = date % 100;
适合数据库分表、按日查询和文件名:
std::string fileName = std::to_string(DateUtil::today()) + ".csv";
注意事项:
getTimeStringstatic string getTimeString(
const std::string& format = "%Y-%m-%d %H:%M:%S");
使用本地时间和 strftime 格式生成字符串。
常用示例:
std::string full = DateUtil::getTimeString();
// 例如 "2026-10-20 14:30:05"
std::string date = DateUtil::getTimeString("%Y-%m-%d");
// "2026-10-20"
std::string compactDate = DateUtil::getTimeString("%Y%m%d");
// "20261020"
std::string compactTime = DateUtil::getTimeString("%H%M%S");
// "143005"
std::string fileName =
DateUtil::getTimeString("export_%Y%m%d_%H%M%S.csv");
常用格式符:
| 格式符 | 含义 | 示例 |
|---|---|---|
%Y |
四位年份 | 2026 |
%y |
两位年份 | 26 |
%m |
两位月份 | 10 |
%d |
两位日期 | 20 |
%H |
24 小时制小时 | 14 |
%I |
12 小时制小时 | 02 |
%M |
分钟 | 30 |
%S |
秒 | 05 |
%F |
年-月-日 |
2026-10-20 |
%T |
时:分:秒 |
14:30:05 |
%w |
星期日为 0 的星期编号 | 0..6 |
%u |
星期一为 1 的星期编号 | 1..7 |
%j |
一年中的第几天 | 001..366 |
%z |
数字时区偏移 | 例如 +0800 |
%Z |
时区名称 | 取决于系统 |
%% |
百分号 | % |
注意事项:
%M 是分钟,月份是小写 %m。%H 是 24 小时制;头文件旧注释中的 %I 是 12 小时制。%a、%A、%b、%B、%c 等结果受系统 Locale 影响,真机上不一定输出中文。strftime 返回 0,本方法返回空字符串。客户按日导出示例:
std::string todayStr = DateUtil::getTimeString("%Y%m%d");
std::string todaySql = DateUtil::getTimeString("%Y-%m-%d");
std::string csvPath = exportDir + "/" + todayStr + ".csv";
std::string sql =
"SELECT * FROM SAMPLE_4_V WHERE STIME >= '" +
todaySql +
" 00:00:00'";
如果表中的 STIME 是毫秒整数,应改用本手册第 6 节的时间戳范围,不能拿格式化字符串直接比较。
getMsTimeStampstatic uint64_t getMsTimeStamp();
返回从设备本次开机开始累计的单调毫秒数,底层使用 CLOCK_MONOTONIC。
它适合计算耗时和超时:
uint64_t started = DateUtil::getMsTimeStamp();
doWork();
uint64_t elapsed = DateUtil::getMsTimeStamp() - started;
std::cout << "耗时 " << elapsed << " ms" << std::endl;
轮询超时:
uint64_t started = DateUtil::getMsTimeStamp();
const uint64_t timeoutMs = 2000;
while (!isReady()) {
if (DateUtil::getMsTimeStamp() - started >= timeoutMs) {
break;
}
}
注意事项:
getMsTimeStamp2 更适合超时判断。toString;它不是 1970 Epoch 时间戳。getMsTimeStamp2()static uint64_t getMsTimeStamp2();
返回当前 Unix Epoch 毫秒时间戳,底层使用 CLOCK_REALTIME:
uint64_t nowMs = DateUtil::getMsTimeStamp2();
// 例如 1792487405123
适合数据库记录、事件时间、采样时间和跨进程交换:
uint64_t eventTime = DateUtil::getMsTimeStamp2();
table.setValue(row, "STIME", std::to_string(eventTime));
注意事项:
getMsTimeStamp()。getTimeStampstatic uint64_t getTimeStamp();
返回当前 Unix Epoch 秒时间戳:
uint64_t nowSec = DateUtil::getTimeStamp();
uint64_t nowMsApprox = nowSec * 1000;
它不包含当前秒内的毫秒部分。需要毫秒精度时直接使用 getMsTimeStamp2()。
| 需求 | 推荐接口 |
|---|---|
| 测量函数执行耗时 | getMsTimeStamp() |
| 实现 2 秒超时 | getMsTimeStamp() |
| 保存采样记录时间 | getMsTimeStamp2() |
| 生成带秒的协议字段 | getTimeStamp() |
| 生成用户可读时间 | getTimeString() |
getUnixTimestatic time_t getUnixTime(
int year,
int month,
int day,
int hour = 0,
int minute = 0,
int second = 0);
把传入字段按 UTC 时间解释,并返回 Unix 秒时间戳。ARM 使用 timegm,Windows 使用 _mkgmtime。
time_t utcMidnight = DateUtil::getUnixTime(2026, 10, 20);
time_t utcTime = DateUtil::getUnixTime(2026, 10, 20, 12, 30, 0);
如果输入表示本地时间,不应直接使用这个接口。以 UTC+8 的本地时间 2026-10-20 08:00:00 为例:
// 方法一:使用本地时间接口,推荐
uint64_t localMs = DateUtil::getMsTimeStamp2(
20261020, 8, 0, 0, 0);
// 方法二:调用 getUnixTime 前自行换算为 UTC 00:00:00
time_t sameMoment = DateUtil::getUnixTime(
2026, 10, 20, 0, 0, 0);
注意事项:
time_t,失败值可能是 -1,调用方需要自行判断。addDays 的内部日历运算,不是常规本地时间构造接口。getMsTimeStamp2(ymd, hour, minute, second, ms)static uint64_t getMsTimeStamp2(
int ymd,
int hour,
int minute,
int second,
int ms);
把给定字段解释为当前时区的本地时间,再转换为 Unix 毫秒时间戳。
uint64_t start = DateUtil::getMsTimeStamp2(
20261020, 0, 0, 0, 0);
uint64_t end = DateUtil::getMsTimeStamp2(
20261020, 23, 59, 59, 999);
推荐使用“左闭右开”的整日范围,避免手工拼 23:59:59.999:
int day = 20261020;
int next = DateUtil::nextDay(day);
uint64_t beginMs = DateUtil::getMsTimeStamp2(day, 0, 0, 0, 0);
uint64_t endMs = DateUtil::getMsTimeStamp2(next, 0, 0, 0, 0);
std::string sql =
"SELECT * FROM SAMPLE_4_V WHERE STIME >= " +
std::to_string(beginMs) +
" AND STIME < " +
std::to_string(endMs);
注意事项:
ymd 必须按 yyyyMMdd 传入,例如 20261020。mktime,会根据当前本地时区转换,并设置 tm_isdst=-1 自动判断夏令时。ms 应限制为 0..999。传负数或大于 999 会跨秒或发生无符号计算异常。mktime 失败返回 -1;当前实现把它转为 uint64_t,会得到非常大的值,接口本身不报告失败。getMsTimeStamp2(string, isstart)static uint64_t getMsTimeStamp2(
string strdate,
bool isstart = true);
接收一个长度为 19 的日期时间字符串,并转换为本地 Unix 毫秒时间戳:
uint64_t begin = DateUtil::getMsTimeStamp2(
"2026-10-20 12:30:45",
true);
// 毫秒部分为 000
uint64_t end = DateUtil::getMsTimeStamp2(
"2026-10-20 12:30:45",
false);
// 毫秒部分为 999
isstart 只控制同一秒内的毫秒部分:
true:追加 000 ms。false:追加 999 ms。它不会自动把时刻改为一天的开始或结束。
当前实现只检查 strdate.length() == 19,然后固定截取以下位置:
yyyy-MM-dd HH:mm:ss
0123456789012345678
因此必须在调用前自行校验:
const std::string text = "2026-10-20 12:30:45";
const std::string pattern =
"^[0-9]{4}-[0-9]{2}-[0-9]{2} "
"[0-9]{2}:[0-9]{2}:[0-9]{2}$";
if (!StringUtil::match(pattern, text)) {
// 格式错误
return;
}
uint64_t value = DateUtil::getMsTimeStamp2(text, true);
仅通过正则仍不能发现 2026-02-31 之类的非法日期;月份、天数和时间范围还应结合 getMonthMaxDay 进一步检查。
长度不等于 19 时直接返回 0。0 同时也是合法的 Unix Epoch 时刻,不能单凭返回值判断输入是否有效。
addDaysstatic void addDays(
int& year,
int& month,
int& day,
int num);
在给定日历日期上增加或减少整天,并通过引用修改年月日。
int year = 2026;
int month = 10;
int day = 20;
DateUtil::addDays(year, month, day, 5);
// 2026-10-25
DateUtil::addDays(year, month, day, -10);
// 2026-10-15
跨月和闰年:
int y = 2024;
int m = 2;
int d = 28;
DateUtil::addDays(y, m, d, 1);
// 2024-02-29
实现按 UTC 日历执行 num * 24 * 60 * 60 秒运算,因此不受本地夏令时一天为 23 或 25 小时的影响,适合“日期加一天”。
注意事项:
num == 0 时立即返回。num 会在 int 秒数乘法阶段溢出,不适合一次增加数万天。gmtime 的返回值未检查,超出平台时间范围时有风险。prevDaystatic int prevDay(int yyyymmdd);
返回前一天的 yyyyMMdd 整数:
int previous = DateUtil::prevDay(20260301); // 20260228
int leapPrevious = DateUtil::prevDay(20240301); // 20240229
nextDaystatic int nextDay(int yyyymmdd);
返回后一天的 yyyyMMdd 整数:
int next = DateUtil::nextDay(20261231); // 20270101
prevDay 和 nextDay 都不验证输入是否是合法 yyyyMMdd。外部输入应先拆分年月日并校验。
getWeekDaystatic uint8_t getWeekDay(
uint32_t y,
uint8_t m,
uint8_t d);
根据日期计算星期编号:
| 返回值 | 星期 |
|---|---|
0 |
星期日 |
1 |
星期一 |
2 |
星期二 |
3 |
星期三 |
4 |
星期四 |
5 |
星期五 |
6 |
星期六 |
uint8_t week = DateUtil::getWeekDay(2026, 10, 20);
// 2,星期二
显示中文星期:
const char* names[] = {
"星期日", "星期一", "星期二", "星期三",
"星期四", "星期五", "星期六"
};
std::string weekName = names[DateUtil::getWeekDay(2026, 10, 20)];
注意事项:
0..6 中的某个值。0 且月份为 1 或 2 时会发生无符号减一,不应使用。strftime("%w") 一致,都是星期日为 0。getMonthMaxDaystatic uint8_t getMonthMaxDay(
uint16_t y,
uint8_t m);
返回指定月份的天数,包含公历闰年规则:
uint8_t a = DateUtil::getMonthMaxDay(2024, 2); // 29
uint8_t b = DateUtil::getMonthMaxDay(2026, 2); // 28
uint8_t c = DateUtil::getMonthMaxDay(2026, 10); // 31
日期合法性检查示例:
bool isValidDate(int year, int month, int day) {
if (year < 1970 || month < 1 || month > 12) {
return false;
}
int maxDay = DateUtil::getMonthMaxDay(
static_cast<uint16_t>(year),
static_cast<uint8_t>(month));
return day >= 1 && day <= maxDay;
}
注意事项:非法月份会进入 default 分支并返回 30,所以必须先检查 m 是否在 1..12。
setDateTimestatic bool setDateTime(
int year,
int month,
int day,
int hour,
int min,
int sec);
ARM 真机上尝试执行以下操作:
mktime 生成时间。/dev/rtc0;代码还包含 /dev/misc/rtc 的备用尝试。RTC_SET_TIME 写硬件 RTC。settimeofday 修改系统时间。SttLooper::notifyAll() 唤醒相关等待。基本示例:
bool ok = DateUtil::setDateTime(
2026, 10, 20,
14, 30, 0);
if (!ok) {
vm->setChar("提示", "系统时间设置失败");
return;
}
// 必须重新读取确认,不能只信返回值
std::string actual = DateUtil::getTimeString();
vm->setChar("当前时间", actual);
注意事项:
true。mktime 可能自动归一化非法日期。struct tm tptr 没有整体清零,tm_isdst 等字段值不确定,夏令时地区可能得到错误结果。/dev/rtc0 打不开时,代码虽然尝试打开 /dev/misc/rtc,但由于当前控制流会在外层分支中无条件 return false,即使备用设备打开成功也不会继续设置,并可能遗留该文件描述符。false;但 settimeofday 的返回值没有检查,RTC 成功后即使系统时钟设置失败也可能返回 true。getTimeString 或 getTimeStamp 核对实际结果。getMsTimeStamp2 变小,但不会影响 getMsTimeStamp 的单调递增。建议在调用前做完整范围校验:
bool valid =
year >= 1970 &&
month >= 1 && month <= 12 &&
day >= 1 && day <= DateUtil::getMonthMaxDay(year, month) &&
hour >= 0 && hour <= 23 &&
min >= 0 && min <= 59 &&
sec >= 0 && sec <= 59;
if (valid) {
DateUtil::setDateTime(year, month, day, hour, min, sec);
}
getTimezonestatic int getTimezone();
当前实现返回的是“UTC 到本地时间所需的 Bias”符号,而不是头文件所述的常规东正西负符号:
| 实际本地时区 | 当前返回值 |
|---|---|
| UTC+8(中国) | -8 |
| UTC+1 | -1 |
| UTC | 0 |
| UTC-5 | +5 |
如果界面需要显示常见的 UTC+8 数值,应取负号:
int displayTimezone = -DateUtil::getTimezone();
// 中国时区通常得到 8
注意事项:
tm_gmtoff,可能包含夏令时影响。TIME_ZONE_INFORMATION::Bias / 60,没有组合标准/夏令时附加 Bias。-5。-12..+12,实现没有主动钳位。setTimezonestatic void setTimezone(int tz);
此方法的输入采用常规符号:东区为正,西区为负。
DateUtil::setTimezone(8); // 设置为 UTC+8
DateUtil::setTimezone(-5); // 设置为 UTC-5
DateUtil::setTimezone(0); // 设置为 UTC
ARM 上 setTimezone(8) 会写入 UTC-8。这是 POSIX TZ 字符串的反向符号规则,不是写错。
ARM 行为:
EnvVar::writeVar("timezone", value) 写配置。setenv("TZ", value, 1) 修改当前进程环境。注意事项:
setTimezone(8) 后,getTimezone() 当前实现通常返回 -8,两个接口的符号语义不对称。getTimeString("%Y-%m-%d %H:%M:%S %z") 检查当前进程显示。convert2HMSstatic string convert2HMS(
int seconds,
bool pad0 = true,
bool mod24 = false);
把非负秒数转换为时、分、秒文本。
示例:
DateUtil::convert2HMS(5); // "00:05"
DateUtil::convert2HMS(65); // "01:05"
DateUtil::convert2HMS(3661); // "1:01:01"
DateUtil::convert2HMS(3661, false); // "1:1:1"
pad0 只控制分钟和秒钟的两位补零,小时不会补零。
mod24=true 时小时对 24 取模:
DateUtil::convert2HMS(25 * 3600, true, true);
// "1:00:00"
DateUtil::convert2HMS(24 * 3600, true, true);
// "00:00",小时变成 0 后不会显示小时字段
注意事项:
mm:ss,不是固定的 hh:mm:ss。00:0-1 等异常文本。seconds 是 int,最大只能表达约 68 年;它适合界面时长,不适合超长周期。int total = 65;
int h = total / 3600;
int m = total / 60 % 60;
int s = total % 60;
std::string fixed = StringUtil::snprintf("%02d:%02d:%02d", h, m, s);
// "00:01:05"
parsestatic system_clock::time_point parse(
const string& timeStr,
const string& format = "%Y-%m-%d %H:%M:%S");
通过 std::get_time 解析字段,再用 mktime 按本地时区生成 system_clock::time_point。
std::chrono::system_clock::time_point point = DateUtil::parse(
"2026-10-20 14:30:00");
time_t seconds = std::chrono::system_clock::to_time_t(point);
自定义格式:
auto point = DateUtil::parse("20/10/2026", "%d/%m/%Y");
注意事项:
fail() 状态,格式错误时仍会把零值或部分值交给 mktime,返回某个归一化时间点。tm 被清零后 tm_isdst 为 0,表示强制“非夏令时”,而不是自动判断。夏令时地区可能相差一小时。mktime 还会归一化超范围日期,例如某些平台会把 2 月 31 日转换到 3 月。外部输入应先检查固定格式、数值范围和月份天数,再调用 parse。
diffInSecondsstatic int diffInSeconds(
const string& time1,
const string& time2);
计算 time1 - time2,单位为秒。两个字符串都固定按 %Y-%m-%d %H:%M:%S 解析。
int seconds = DateUtil::diffInSeconds(
"2026-10-20 15:00:03",
"2026-10-20 15:00:00");
// 3
int negative = DateUtil::diffInSeconds(
"2026-10-20 14:59:00",
"2026-10-20 15:00:00");
// -60
跨日示例:
int seconds = DateUtil::diffInSeconds(
"2026-10-21 00:00:00",
"2026-10-20 00:00:00");
// 通常为 86400;夏令时切换地区可能不是 86400
注意事项:
parse 的全部限制:不报告解析失败、按本地时区处理、夏令时标志固定为非夏令时。int,约 68 年以上的差值可能溢出。uint64_t/int64_t 差值更明确。toStringstatic string toString(
uint64_t ms,
const string& format = "");
通过工程默认 SQLite 数据库把 Unix 毫秒时间戳转换为本地时间文本。
默认格式:
uint64_t nowMs = DateUtil::getMsTimeStamp2();
std::string text = DateUtil::toString(nowMs);
// 形如 "2026-10-20 14:30:05"
自定义 SQLite strftime 格式:
std::string date = DateUtil::toString(nowMs, "%Y-%m-%d");
std::string compact = DateUtil::toString(nowMs, "%Y%m%d_%H%M%S");
内部执行的 SQL 逻辑等价于:
SELECT datetime(ms / 1000, 'unixepoch', 'localtime');
或者:
SELECT strftime(format, ms / 1000, 'unixepoch', 'localtime');
注意事项:
DBMgr::getdb() 和 TTable,默认数据库必须已经初始化;它不是纯字符串函数。ms / 1000 会丢弃毫秒部分,结果只能显示到秒。format 使用 SQLite strftime 规则,不完全等同于 C/C++ strftime,支持项取决于设备上的 SQLite 版本。sqlEsc。不要把用户输入或网络输入直接作为格式串。'localtime' 使用当前环境时区,改变 TZ 后结果会变化。如果只需格式化当前时间,优先使用不依赖数据库的 getTimeString。如果需要格式化任意时间戳且允许使用 HMI Runtime,也可把毫秒除以 1000 后调用 StringUtil::formatDate。
std::string fileName =
DateUtil::getTimeString("%Y%m%d") + ".csv";
std::string csvPath = exportDir + "/" + fileName;
int day = DateUtil::today();
int tomorrow = DateUtil::nextDay(day);
uint64_t beginMs = DateUtil::getMsTimeStamp2(day, 0, 0, 0, 0);
uint64_t endMs = DateUtil::getMsTimeStamp2(tomorrow, 0, 0, 0, 0);
std::string sql =
"SELECT * FROM SAMPLE_4_V "
"WHERE STIME >= " + std::to_string(beginMs) +
" AND STIME < " + std::to_string(endMs) +
" ORDER BY STIME";
左闭右开范围能覆盖当天所有毫秒,同时避免下一天 00:00:00.000 被重复计入。
std::string date = DateUtil::getTimeString("%Y-%m-%d");
std::string nextDate;
int tomorrow = DateUtil::nextDay(DateUtil::today());
nextDate = StringUtil::snprintf(
"%04d-%02d-%02d",
tomorrow / 10000,
tomorrow / 100 % 100,
tomorrow % 100);
std::string sql =
"SELECT * FROM SAMPLE_4_V "
"WHERE STIME >= '" + date + " 00:00:00' "
"AND STIME < '" + nextDate + " 00:00:00' "
"ORDER BY STIME";
这要求数据库中的文本日期固定为可按字典序排序的 yyyy-MM-dd HH:mm:ss。
uint64_t started = DateUtil::getMsTimeStamp();
std::string err;
bool ok = FileUtil::exportDB2CSV(
dbPath,
tableName,
sql,
csvPath,
err);
uint64_t elapsed = DateUtil::getMsTimeStamp() - started;
std::string message = ok
? "导出完成,耗时 " + std::to_string(elapsed) + " ms"
: "导出失败: " + err;
vm->setChar("导出提示", message);
不要用 getMsTimeStamp2() 测耗时,因为导出过程中如果发生校时,结果可能跳变。
DateUtil::setTimezone(8);
bool started = DateUtil::setDateTime(
2026, 10, 20,
14, 30, 0);
std::string actual = DateUtil::getTimeString(
"%Y-%m-%d %H:%M:%S %z");
if (!started) {
vm->setChar("提示", "RTC 设置失败");
} else {
vm->setChar("提示", "当前系统时间: " + actual);
}
在 Windows 模拟器上,这个示例只能验证界面流程,不能验证系统设置是否生效。
getMsTimeStamp()。getMsTimeStamp2(),并明确字段单位为毫秒。getTimeString()。getMsTimeStamp2(ymd, ...);需要 UTC 字段转换时才使用 getUnixTime()。[当天 00:00, 下一天 00:00) 左闭右开范围。parse 或 getMsTimeStamp2(string) 的返回值判断输入是否合法。getTimezone() 当前返回值与常见显示符号相反,中国时区通常返回 -8。setDateTime 和 setTimezone 必须在 ARM 真机验证;模拟器不会真正设置。setDateTime 后重新读取时间核对,不要仅依赖布尔返回值。toString 依赖默认数据库,普通当前时间格式化优先使用 getTimeString。