时间类型
在进行程序开发的过程中,免不了和时间打交道,下面就是一些关于WIndows和Linux的时间类型分析
预习知识
Unix时间戳,Unix时间,POSIX时间,这三种表达方式都是一样的。代表了从格林威治时间(世界时)1970年1月1号00时00分00秒起知道现在的秒数。
因为操作系统一般用32位2进制数表示时间,那么可以知道系统Unix时间戳最多可以使用到2038年1月19号3时14分07秒,在下一秒时会发生溢出。如果使用64位二进制则不会出现错误。
一般来说时间分为:
- 本地时间
- 格林位置时间(世界时):根据地球转速周期性差异矫正后时间
- 时间协调时间:以地球自转为基础的时间标准
时间在Linux中的两种表示方法
-
time_t:存储了从1970年到现在经过了多少秒。如果想要更加精确的时间,可以使用struct timeval,可以精确到微秒
struct timeval { long tv_sec; //秒 long tv_usec; //微秒 }
-
tm:用结构分别存储年、月、日、时、分、秒
struct tm { int tm_sec; //秒,正常范围0-59, 但允许至61 int tm_min; //分钟,0-59 int tm_hour; //小时, 0-23 int tm_mday; //日,即一个月中的第几天,1-31 int tm_mon; 1+p->tm_mon; //月, 从一月算起,0-11 int tm_year; 1900+ p->tm_year; //年, 从1900至今已经多少年 int tm_wday; //星期,一周中的第几天, 从星期日算起,0-6 int tm_yday; //从今年1月1日到目前的天数,范围0-365 int tm_isdst; //夏令时,冬令时的标志(不要忘记赋值,不知道就-1) };
需要特别注意的是,年份是从1900年起至今多少年,而不是直接存储如2011年,月份从0开始的,0表示一月,星期也是从0开始的, 0表示星期日,1表示星期一。
常用的时间函数
-
#include <time.h> char *asctime(const struct tm* timeptr);
该函数将tm格式的时间转化为真实世界的时间,类型为字符串。
注意:该函数的输出格式为Wed Aug 14 04:21:25 2019,这个格式尽量不要参与运算。
-
char *ctime(const time_t *timep);
将time_t格式的时间转化为真实世界实参,类型为字符串。
注意:该函数的输出格式为Wed Aug 14 04:21:25 2019,这个格式尽量不要参与运算。
-
double difftime(time_t time1, time_t time2);
返回两个时间相差的秒数,其实time_t是unsigned long类型,可以直接相减
-
int gettimeofday(struct timeval *tv, struct timezone *tz);
返回当前时间距离1970年的秒数和微秒数,后面的参数是时区
-
struct tm* gmtime(const time_t *timep);
将time_t时间转化为没有经过时区转换的UTC时间,转化后的格式是struct tm结构指针
-
stuct tm* localtime(const time_t *timep);
将time_t转化为经过时区转换的时间,转化后的格式是struct tm结构指针
-
time_t mktime(struct tm* timeptr);
将tm格式时间转化为time_t的格式(自1970到今天的秒数)
-
time_t time(time_t *t);
获得现在时间的time_t的格式(自1970到现在的秒数)
时间格式的转化
在实际使用中我们经常希望将事件格式转化为我们希望的到的格式,而不是asctime或者ctime所给出的格式
时间与字符串的相互转化
我们知道Unix环境下有strptime函数,所以在Unix和windows环境下代码有些许差别
前置知识
strftime函数
-
函数定义
C 库函数 size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr) 根据 format 中定义的格式化规则,格式化结构 timeptr 表示的时间,并把它存储在 str 中。
-
函数声明
size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr);
-
函数参数类型
- str – 这是指向目标数组的指针,用来复制产生的 C 字符串
- maxsize – 这是被复制到 str 的最大字符数
- format – 这是 C 字符串,包含了普通字符和特殊格式说明符的任何组合。这些格式说明符由函数替换为表示 tm 中所指定时间的相对应值
- 格式说明符:
%a 星期几的简写 %A 星期几的全称 %b 月分的简写 %B 月份的全称 %c 标准的日期的时间串 %C 年份的后两位数字 %d 十进制表示的每月的第几天 %D 月/天/年 %e 在两字符域中,十进制表示的每月的第几天 %F 年-月-日 %g 年份的后两位数字,使用基于周的年 %G 年分,使用基于周的年 %h 简写的月份名 %H 24小时制的小时 %I 12小时制的小时 %j 十进制表示的每年的第几天 %m 十进制表示的月份 %M 十时制表示的分钟数 %n 新行符 %p 本地的AM或PM的等价显示 %r 12小时的时间 %R 显示小时和分钟:hh:mm %S 十进制的秒数 %t 水平制表符 %T 显示时分秒:hh:mm:ss %u 每周的第几天,星期一为第一天 (值从0到6,星期一为0) %U 第年的第几周,把星期日做为第一天(值从0到53) %V 每年的第几周,使用基于周的年 %w 十进制表示的星期几(值从0到6,星期天为0) %W 每年的第几周,把星期一做为第一天(值从0到53) %x 标准的日期串 %X 标准的时间串 %y 不带世纪的十进制年份(值从0到99) %Y 带世纪部分的十制年份 %z,%Z 时区名称,如果不能得到时区名称则返回空字符。 %% 百分号
strptime函数
-
函数定义
strptime主要用于把字符串转换成分解时间,与strftime的作用相反。都位于<time.h>中,原型如下:
extern char *strptime (__const char *__restrict __s, __const char *__restrict __fmt, struct tm *__tp); -
函数形参
第一个形参是传入的时间格式字符串"2022-09-01 12:23:09"
第二个形参是需要传入的时间格式
第三个参数是一个tm的结构体指针
需要包括的头文件如下:
#include <iostream>
#include <time.h>
#include <cstdlib>
#include <string>
时间转字符串代码(Unix,windows)
time_t t; //秒时间
tm* local; //本地时间
tm* gmt; //格林威治时间
char buf[128]= {0};
t = time(NULL); //获取目前秒时间
local = localtime(&t); //转为本地时间
strftime(buf, 64, "%Y-%m-%d %H:%M:%S", local);
std::cout << buf << std::endl;
gmt = gmtime(&t);//转为格林威治时间
strftime(buf, 64, "%Y-%m-%d %H:%M:%S", gmt);
std::cout << buf << std::endl;
字符串转时间代码Unix
tm tm_;
time_t t_;
char buf[128]= {0};
strcpy(buf, "2012-01-01 14:00:00");
strptime(buf, "%Y-%m-%d %H:%M:%S", &tm_); //将字符串转换为tm时间
tm_.tm_isdst = -1;
t_ = mktime(&tm_); //将tm时间转换为秒时间
t_ += 3600; //秒数加3600
tm_ = *localtime(&t_);//输出时间
strftime(buf, 64, "%Y-%m-%d %H:%M:%S", &tm_);
std::cout << buf << std::endl;
字符串转时间代码Windows
time_t StringToDatetime(char *str)
{
tm tm_;
int year, month, day, hour, minute,second;
sscanf(str,"%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second);
tm_.tm_year = year-1900;
tm_.tm_mon = month-1;
tm_.tm_mday = day;
tm_.tm_hour = hour;
tm_.tm_min = minute;
tm_.tm_sec = second;
tm_.tm_isdst = 0;
time_t t_ = mktime(&tm_); //已经减了8个时区
return t_; //秒时间
}