std::time_get<CharT,InputIt>::get, std::time_get<CharT,InputIt>::do_get
来自 cppreference.com
定义在头文件 <locale> 中 |
||
public: iter_type get( iter_type beg, iter_type end, std::ios_base& str, |
(1) | (自 C++11 起) |
protected: virtual iter_type do_get( iter_type beg, iter_type end, std::ios_base& str, |
(2) | (自 C++11 起) |
1) 根据字符序列 [fmtbeg, fmtend) 中提供的格式,从输入字符序列 [beg, end) 解析日期和时间。预期格式遵循下面描述的格式,尽管可以通过覆盖
do_get
来定制每个格式说明符的实际处理。get
函数执行以下操作:首先,通过执行 err = std::ios_base::goodbit 来清除 err 中的错误位。然后进入循环,该循环在以下任何条件变为真时终止(按此顺序检查)a) 从格式字符串中读取了所有字符(fmtbeg == fmtend)。
b) 发生了解析错误(err != std::ios_base::goodbit)。
c) 从输入序列中读取了所有字符(beg == end。如果此条件终止循环,则函数在 err 中设置
eofbit
和 failbit
。- 在循环体中,将执行以下步骤
a) 如果格式字符串中的下一个字符是 '%',后面跟着一个或两个字符,形成一个有效的 std::get_time 转换说明符(见下文),则这些字符将用于调用 do_get(beg, end, str, err, t, format, modifier),其中 format 是主要的转换说明符字符,而 modifier 是可选的修饰符(如果存在,则出现在
%
和格式字符之间)。如果没有修饰符,则使用值 '\0'。如果格式字符串是模棱两可的,或者在 %
后结束得太早而无法确定转换说明符,则在 err 中设置 eofbit
并终止循环。如果在调用 do_get
后,err 中没有设置任何错误位,则该函数将 fmtbeg 递增到转换说明符之后,并继续循环。b) 如果下一个字符是空格,如流 str 中提供的区域设置所指示的那样(即 std::isspace(*fmtbeg, str.getloc()) == true,则该函数会一直递增 fmtbeg,直到它等于 fmtend 或指向一个非空格字符。
c) 如果格式字符串中的下一个字符与输入流中的下一个字符在不区分大小写比较时等效,则该函数将这两个序列都向前移动一个字符 ++fmtbeg, ++beg; 并继续循环,否则,它在 err 中设置
failbit
。- 首先,通过执行 err = std::ios_base::goodbit 来清除 err 中的错误位。然后从输入序列 [beg, end) 中读取字符,这些字符由 std::time_get 格式说明符组成,该说明符是通过组合 '%'、modifier(如果它不是 '\0')和 format 形成的。如果这些字符没有组合成有效的转换说明符,则在 err 中设置
failbit
。如果在读取字符后遇到输入流的末尾,则在 err 中设置eofbit
。如果成功解析了输入字符串,则更新 *t 的相应字段。
- 首先,通过执行 err = std::ios_base::goodbit 来清除 err 中的错误位。然后从输入序列 [beg, end) 中读取字符,这些字符由 std::time_get 格式说明符组成,该说明符是通过组合 '%'、modifier(如果它不是 '\0')和 format 形成的。如果这些字符没有组合成有效的转换说明符,则在 err 中设置
- 对于复杂的转换说明符,例如 '%x' 或 '%c',或使用修饰符 'E' 和 'O' 的指令,该函数可能无法确定要存储在 *t 中的某些值。在这种情况下,它会在 err 中设置
eofbit
,并将这些字段保留在未指定的状太。
- 对于复杂的转换说明符,例如 '%x' 或 '%c',或使用修饰符 'E' 和 'O' 的指令,该函数可能无法确定要存储在 *t 中的某些值。在这种情况下,它会在 err 中设置
内容 |
[编辑] 参数
beg | - | 迭代器,指定要解析的序列的开始 |
end | - | 要解析的序列的结束迭代器之后的迭代器 |
str | - | 一个流对象,该函数在需要时使用它来获取区域设置方面,例如 std::ctype 用于跳过空格或 std::collate 用于比较字符串 |
err | - | 流错误标志对象,该函数通过它修改以指示错误 |
t | - | 指向 std::tm 对象的指针,该对象将保存此函数调用的结果 |
fmtbeg | - | 指向指定转换格式的 char_type 字符序列的第一个字符的指针(参见下文) |
fmtend | - | 指向指定转换格式的 char_type 字符序列的最后一个字符之后的指针 |
format | - | 命名转换说明符的字符 |
modifier | - | 可能出现在 % 和转换说明符之间的可选修饰符 |
格式字符串由零个或多个转换说明符、空格字符和普通字符(除 %
外)组成。每个普通字符都应与输入流中的一个字符进行不区分大小写的比较匹配。每个空格字符都与输入字符串中的任意空格匹配。每个转换说明符都以 %
字符开头,可选地后跟 E
或 O
修饰符(如果区域设置不支持则忽略),后跟确定说明符行为的字符。格式说明符与 POSIX 函数 strptime()
匹配
转换 说明符 |
解释 | 写入字段 |
---|---|---|
%
|
匹配文字 % 。完整的转换说明符必须是 %% |
(无) |
t
|
匹配任何空格 | (无) |
n
|
匹配任何空格 | (无) |
年 | ||
Y
|
将完整年解析为 4 位十进制数,允许前导零,但不是必需的 | tm_year
|
EY
|
解析年的替代表示,例如平成23年(平成 23 年),它在 ja_JP 区域设置中将 2011 写入 tm_year | tm_year
|
y
|
解析年的后 2 位作为十进制数。范围 [69,99] 导致值 1969 到 1999,范围 [00,68] 导致 2000-2068 |
tm_year
|
Oy
|
使用替代数字系统解析年的后 2 位,例如,十一在 ja_JP 区域设置中解析为 11 | tm_year
|
Ey
|
解析年作为区域设置的替代日历周期 %EC 的偏移量 |
tm_year
|
C
|
解析年的前 2 位作为十进制数(范围 [00,99] ) |
tm_year
|
EC
|
解析区域设置替代表示中的基年(时期)名称,例如,在 ja_JP 中为平成(平成时代) | tm_year
|
月 | ||
b
|
解析月份名称,可以是完整的,也可以是缩写的,例如 Oct |
tm_mon
|
h
|
b 的同义词 |
tm_mon
|
B
|
b 的同义词 |
tm_mon
|
m
|
将月解析为十进制数(范围 [01,12] ),允许前导零,但不是必需的 |
tm_mon
|
Om
|
使用替代数字系统解析月,例如,十二在 ja_JP 区域设置中解析为 12 | tm_mon
|
周 | ||
U
|
将年中的周解析为十进制数(星期日是一周的第一天)(范围 [00,53] ),允许前导零,但不是必需的 |
tm_year 、tm_wday 、tm_yday |
OU
|
解析年中的周,如同通过 %U 一样,使用替代数字系统,例如,五十二在 ja_JP 区域设置中解析为 52 |
tm_year 、tm_wday 、tm_yday |
W
|
将年中的周解析为十进制数(星期一是周的第一天)(范围 [00,53] ),允许前导零,但不是必需的 |
tm_year 、tm_wday 、tm_yday |
OW
|
解析年中的周,如同通过 %W 一样,使用替代数字系统,例如,五十二在 ja_JP 区域设置中解析为 52 |
tm_year 、tm_wday 、tm_yday |
年中的日/月中的日 | ||
j
|
将年中的日解析为十进制数(范围 [001,366] ),允许前导零,但不是必需的 |
tm_yday
|
d
|
将月中的日解析为十进制数(范围 [01,31] ),允许前导零,但不是必需的 |
tm_mday
|
Od
|
使用替代数字系统解析月中的日,例如,二十七在 ja_JP 区域设置中解析为 27,允许前导零,但不是必需的 | tm_mday
|
e
|
d 的同义词 |
tm_mday
|
Oe
|
Od 的同义词 |
tm_mday
|
星期 | ||
a
|
解析星期的名称,可以是完整的,也可以是缩写的,例如 Fri |
tm_wday
|
A
|
a 的同义词 |
tm_wday
|
w
|
将星期解析为十进制数,其中星期日为 0 (范围 [0-6] ) |
tm_wday
|
Ow
|
将星期解析为十进制数,其中星期日为 0 ,使用替代数字系统,例如,二在 ja_JP 区域设置中解析为 2 |
tm_wday
|
小时、分钟、秒 | ||
H
|
将小时解析为十进制数,24 小时制(范围 [00-23] ),允许前导零,但不是必需的 |
tm_hour
|
OH
|
从 24 小时制中解析小时,使用替代数字系统,例如,十八在 ja_JP 区域设置中解析为 18 | tm_hour
|
I
|
将小时解析为十进制数,12 小时制(范围 [01,12] ),允许前导零,但不是必需的 |
tm_hour
|
OI
|
从 12 小时制中解析小时,使用替代数字系统,例如,六在 ja_JP 区域设置中解析为 06 | tm_hour
|
M
|
将分钟解析为十进制数(范围 [00,59] ),允许前导零,但不是必需的 |
tm_min
|
OM
|
使用替代数字系统解析分钟,例如,二十五在 ja_JP 区域设置中解析为 25 | tm_min
|
S
|
将秒解析为十进制数(范围 [00,60] ),允许前导零,但不是必需的 |
tm_sec
|
OS
|
使用替代数字系统解析秒,例如,二十四在 ja_JP 区域设置中解析为 24 | tm_sec
|
其他 | ||
c
|
解析区域设置的标准日期和时间字符串格式,例如 Sun Oct 17 04:41:13 2010 (区域设置相关) |
全部 |
Ec
|
解析区域设置的替代日期和时间字符串格式,例如,在 ja_JP 区域设置中,期望 平成23年(平成 23 年)而不是 2011年(2011 年) | 全部 |
x
|
解析区域设置的标准日期表示 | 全部 |
Ex
|
解析区域设置的替代日期表示,例如,在 ja_JP 区域设置中,期望 平成23年(平成 23 年)而不是 2011年(2011 年) | 全部 |
X
|
解析区域设置的标准时间表示 | 全部 |
EX
|
解析区域设置的替代时间表示 | 全部 |
D
|
相当于 "%m / %d / %y " | tm_mon 、tm_mday 、tm_year |
r
|
解析区域设置的标准 12 小时制时间(在 POSIX 中,"%I : %M : %S %p") | tm_hour 、tm_min 、tm_sec |
R
|
相当于 "%H : %M" | tm_hour 、tm_min |
T
|
相当于 "%H : %M : %S" | tm_hour 、tm_min 、tm_sec |
p
|
解析区域设置的上午或下午的等效项 | tm_hour
|
注意:不写入 tm_isdst
,需要为诸如 mktime
之类的函数显式设置它
[编辑] 返回值
指向 [beg, end) 中成功解析的最后一个字符之后的迭代器。
[编辑] 注释
格式字符串中不区分大小写的比较用于非空格非 '%' 字符,std::collate 区域设置方面通常(但并非总是)使用 str 提供的区域设置方面。
如果遇到解析错误,此函数的许多实现会完全不理会 *t。
这些函数是否将 *t 中未直接设置的字段清零是不确定的:可移植程序应在调用 get()
之前将每个字段初始化为零。
[编辑] 示例
运行此代码
#include <iomanip> #include <iostream> #include <locale> #include <sstream> int main() { std::istringstream ss("2026-März-12 23:45:56"); ss.imbue(std::locale("de_DE.utf8")); auto& f = std::use_facet<std::time_get<char>>(ss.getloc()); std::tm t{}; std::string s = "%Y-%b-%d %H:%M:%S"; std::ios_base::iostate err = std::ios_base::goodbit; auto ret = f.get({ss}, {}, ss, err, &t, &s[0], &s[0] + s.size()); ss.setstate(err); std::istreambuf_iterator<char> last{}; if (ss) { std::cout << "Successfully parsed as " << std::put_time(&t, "%c") << '\n'; if (ret != last) { std::cout << "Remaining content: "; std::copy(ret, last, std::ostreambuf_iterator<char>(std::cout)); } else std::cout << "The input was fully consumed."; } else { std::cout << "Parse failed.\nUnparsed string: "; std::copy(ret, last, std::ostreambuf_iterator<char>(std::cout)); } std::cout << '\n'; }
输出
Successfully parsed as Sun Mar 12 23:45:56 2026 The input was fully consumed.
[编辑] 参见
(C++11) |
解析指定格式的日期/时间值 (函数模板) |