POCO C++库学习和分析 -- 日期与时间
在Poco库中,与时间和日期相关的一些类,其内部实现是非常简单的。看相关文档时,比较有意思的倒是历史上的不同时间表示法。
1. 系统时间函数
在编程时,时间函数不可避免的会被使用。linux系统下相关时间的数据结构有time_t,timeval,timespec,tm,clock_t; windows下time_t,tm,SYSTEMTIME,FILETIME,clock_t。其中clock_t、timeval、timespec用于表示时间跨度,time_t、tm、SYSTEMTIME,FILETIME用于表示绝对时间。不同的数据结构之间,多少也有些差异。首先这些时间结构体的精度不同,Second(time_t/tm), microsecond(timeval/SYSTEMTIME), 100nanoSeconds(FILETIME),nanoSeconds(timespec)。还有一些结构和操作系统相关,如clock_t,windows下为1毫秒,POSIX 下为1微秒,对应clock_t,不同平台的差异,可以用宏CLOCKS_PER_SEC解决。
起始时间不同,time_t起始于1970年1月1日0时0分0秒,tm表示起始于1900年,SYSTEMTIME/FILETIME起始于1601年,clock起始于机器开机。
上面各个时间的定义如下:
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME;
typedef struct _SYSTEMTIME
{
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds; // 毫秒
} SYSTEMTIME, *PSYSTEMTIME;
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日,以此类推 */
int tm_isdst; /* 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。*/
};
typedef __time64_t time_t; // 秒
struct timeval
{
long tv_sec; /* seconds */
long tv_usec; /* and microseconds 毫秒*/
};
struct timespec
{
__time_t tv_sec; /*seconds 秒*/
long int tv_nsec; /*nanoseconds 纳秒*/
}
typedef unsigned long clock_t; // 毫秒
同这些数据结构相关联,C语言为tm,time_t提供了一组函数用于时间运算和数据结构转换:
// 日历时间(一个用time_t表示的整数)
// 比较日历时间
double difftime(time_t time1, time_t time0);
// 获取日历时间
time_t time(time_t * timer);
// 转换日历时间为字符串
char * ctime(const time_t *timer);
// 转换日历时间为我们平时看到的把年月日时分秒分开显示的时间格式tm(GMT timezone)
struct tm * gmtime(const time_t *timer);
// 转换日历时间为我们平时看到的把年月日时分秒分开显示的时间格式tm(本地 timezone)
struct tm * localtime(const time_t * timer);
// 关于本地时间的计算公式:
localtime = utctime[Gmt time] + utcOffset()[时区偏移] + dst()[夏令时偏移]
// 把tm转换为字符串
char * asctime(const struct tm * timeptr);
// 把tm转换为日历时间
time_t mktime(struct tm * timeptr);
// 获取开机以来的微秒数
clock_t clock (void);
Windows下特有的时间转换函数包括:
GetLocalTime能够得到本地电脑设置时区的时间,得到的类型是SYSTEMTIME的类型。
void GetSystemTime(LPSYSTEMTIME lpSystemTime); // GetSystemTime函数获得当前的UTC时间
void GetLocalTime(LPSYSTEMTIME lpSystemTime); // GetLocalTime获得当前的本地时间
BOOL SystemTimeToFileTime(const SYSTEMTIME* lpSystemTime,
LPFILETIME lpFileTime);
BOOL FileTimeToSystemTime(const FILETIME* lpFileTime,
LPSYSTEMTIME lpSystemTime);
BOOL LocalFileTimeToFileTime(const FILETIME* lpLocalFileTime,
LPFILETIME lpFileTime);
BOOL FileTimeToLocalFileTime(const FILETIME* lpFileTime,
LPFILETIME lpLocalFileTime);
Windows下特有的获取时间精度的函数包括(精度微秒):
BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
BOOL QueryPerformanceCounter(LARGE_INTEGER *lpCount);
1. 获取绝对时间
2. 获取两个时间点的相对时间
2. Timestamp类
同C语言中函数类似,Poco中定义了自己的时间类。Timestamp类似于time_t,用于获取比较日历时间。Timestamp定义如下:
class Foundation_API Timestamp
{
public:
typedef Int64 TimeVal; /// monotonic UTC time value in microsecond resolution
typedef Int64 UtcTimeVal; /// monotonic UTC time value in 100 nanosecond resolution
typedef Int64 TimeDiff; /// difference between two timestamps in microseconds
Timestamp();
/// Creates a timestamp with the current time.
Timestamp(TimeVal tv);
/// Creates a timestamp from the given time value.
Timestamp(const Timestamp& other);
/// Copy constructor.
~Timestamp();
/// Destroys the timestamp
Timestamp& operator = (const Timestamp& other);
Timestamp& operator = (TimeVal tv);
void swap(Timestamp& timestamp);
/// Swaps the Timestamp with another one.
void update();
/// Updates the Timestamp with the current time.
bool operator == (const Timestamp& ts) const;
bool operator != (const Timestamp& ts) const;
bool operator > (const Timestamp& ts) const;
bool operator >= (const Timestamp& ts) const;
bool operator < (const Timestamp& ts) const;
bool operator <= (const Timestamp& ts) const;
Timestamp operator + (TimeDiff d) const;
Timestamp operator - (TimeDiff d) const;
TimeDiff operator - (const Timestamp& ts) const;
Timestamp& operator += (TimeDiff d);
Timestamp& operator -= (TimeDiff d);
std::time_t epochTime() const;
/// Returns the timestamp expressed in time_t.
/// time_t base time is midnight, January 1, 1970.
/// Resolution is one second.
UtcTimeVal utcTime() const;
/// Returns the timestamp expressed in UTC-based
/// time. UTC base time is midnight, October 15, 1582.
/// Resolution is 100 nanoseconds.
TimeVal epochMicroseconds() const;
/// Returns the timestamp expressed in microseconds
/// since the Unix epoch, midnight, January 1, 1970.
TimeDiff elapsed() const;
/// Returns the time elapsed since the time denoted by
/// the timestamp. Equivalent to Timestamp() - *this.
bool isElapsed(TimeDiff interval) const;
/// Returns true iff the given interval has passed
/// since the time denoted by the timestamp.
static Timestamp fromEpochTime(std::time_t t);
/// Creates a timestamp from a std::time_t.
static Timestamp fromUtcTime(UtcTimeVal val);
/// Creates a timestamp from a UTC time value.
static TimeVal resolution();
/// Returns the resolution in units per second.
/// Since the timestamp has microsecond resolution,
/// the returned value is always 1000000.
private:
TimeVal _ts;
};
Timestamp内部定义了一个Int64的变量_ts。存储了一个基于utc时间的64位int值,理论上可以提供微秒级的精度(实际精度依赖于操作系统)。由于Poco::Timestamp是基于UTC(世界标准时间或世界協調時間)的,所以它是独立于时区设置的。Poco::Timestamp实现了值语义