开发中对于特定格式的日期和格式获取很常见,这里给出一系列工具函数:
#include <time.h>
#include <sstream>
using namespace std;
// time转格式化字符串=====================================
std::string ShowDateTime(const tm& t, const string& format)
{
char s[100];
strftime(s, sizeof(s), format.c_str(), &t);
return string(s);
}
std::string ShowDateTime(const time_t& t, const string& format)
{
tm _tm;
gmtime_r(&t, &_tm);
return ShowDateTime(_tm, format);
}
std::string ShowDateTime( const tm& t, const char& dateDiv = '-', const char& timeDiv = ':' )
{
ostringstream format;
format << "%Y" << dateDiv << "%m" << dateDiv << "%d" << ' ';
format << "%H" << timeDiv << "%M" << timeDiv << "%S";
return ShowDateTime(t, format.str());
}
std::string ShowDateTime( const time_t& t, const char& dateDiv = '-', const char& timeDiv = ':' )
{
ostringstream format;
format << "%Y" << dateDiv << "%m" << dateDiv << "%d" << ' ';
format << "%H" << timeDiv << "%M" << timeDiv << "%S";
return ShowDateTime(t, format.str());
}
std::string ShowYMD( const time_t& t, const char& dateDiv = '-' )
{
ostringstream format;
format << "%Y" << dateDiv << "%m" << dateDiv << "%d";
return ShowDateTime(t, format.str());
}
std::string ShowHMS( const time_t& t, const char& timeDiv = ':' )
{
ostringstream format;
format << "%H" << timeDiv << "%M" << timeDiv << "%S";
return ShowDateTime(t, format.str());
}
std::string ShowHM( const time_t& t, const char& timeDiv = ':' )
{
ostringstream format;
format << "%H" << timeDiv << "%M";
return ShowDateTime(t, format.str());
}
// 格式化字符串转time=====================================
time_t mkgmtime(tm * pTm)
{
unsigned int year = pTm->tm_year + 1900;
unsigned int mon = pTm->tm_mon + 1;
unsigned int day = pTm->tm_mday;
unsigned int hour = pTm->tm_hour;
unsigned int min = pTm->tm_min;
unsigned int sec = pTm->tm_sec;
if (0 >= (int)(mon -= 2)) { /* 1..12 -> 11,12,1..10 */
mon += 12; /* Puts Feb last since it has leap day */
year -= 1;
}
return (((
(unsigned long)(year / 4 - year / 100 + year / 400 + 367 * mon / 12 + day) +
year * 365 - 719499
) * 24 + hour /* now have hours */
) * 60 + min /* now have minutes */
) * 60 + sec; /* finally seconds */
}
time_t str2time(const string& dateStr, const string& format)
{
tm t;
memset(&t, 0, sizeof(tm));
::strptime(dateStr.c_str(), format.c_str(), &t);// windows下用不了
return mkgmtime(&t);
}
time_t str2time(const string& dateStr, const char& dateDiv = '-', const char& timeDiv = ':')
{
string format = "%Y-%m-%d %H:%M:%S";
if (dateDiv != '-')
{
format[2] = format[5] = dateDiv;
}
if (timeDiv != ':')
{
format[11] = format[14] = timeDiv;
}
return str2time(dateStr.c_str(), format);
}
time_t str2date(const string& dateStr, const char& dateDiv = '-')
{
string format = "%Y-%m-%d";
if (dateDiv != '-')
{
format[2] = format[5] = dateDiv;
}
return str2time(dateStr.c_str(), format);
}
// 使用====================================
int main() {
time_t now = time(0);
cout << ShowYMD(now) << endl;
cout << str2date(ShowYMD(now)) << endl;
system("pause");// 暂停以显示终端窗口
return 0;
}
代码中,第一部分是time转格式化字符串,这里要注意,time库提供了time_t和tm两种格式的时间,time_t是1970年01月01日00时00分00秒到现在所经过的秒数,而tm是一个结构体,如下:
struct tm {
int tm_sec; /* 秒 – 取值区间为[0,59] */
int tm_min; /* 分 - 取值区间为[0,59] */
int tm_hour; /* 时 - 取值区间为[0,23] */
int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */
int tm_mon; /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */
int tm_year; /* 年份,其值等于实际年份减去1900 */
int tm_wday; /* 星期 – 取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 */
int tm_yday; /* 从每年的1月1日开始的天数 – 取值区间为[0,365],其中0代表1月1日,1代表1月2日
};
转换控制符 说明
%a 星期几的简写形式
%A 星期几的全称
%b 月份的简写形式
%B 月份的全称
%c 日期和时间
%d 月份中的日期,0-31
%H 小时,00-23
%I 12进制小时钟点,01-12
%j 年份中的日期,001-366
%m 年份中的月份,01-12
%M 分,00-59
%p 上午或下午
%s 秒,00-60
%u 星期几,1-7
%w 星期几,0-6
%x 当地格式的日期
%X 当地格式的时间
%y 年份中的最后两位数,00-99
%Y 年
%Z 地理时区名称
所以我们代码中做时间到字符串的转换操作时,都要经过“time_t变量——tm结构体——格式化字符串”三者之间的来回转换。当从时间转到字符串时,我们获取当前的time_t,然后用gmtime_r函数转成tm结构体,再用strftime函数通过设好的format格式来得到格式化的日期时间字符串。
代码中提供了很多常见的字符串格式,也可以根据自己的需要继续增加。
而从格式化字符串转回time_t秒数也很简单了,把上述流程反过来即可,创建一个tm结构体,通过strptime函数将格式化(需明确指定)的字符串转为tm结构体,然后通过mkgmtime函数得到time_t秒数。