先说个概念: Coordinated Universal Time(UTC):又称为世界标准时间; 比如,中国内地的时间与UTC的时差为+8,也就是UTC+8。 Calendar Time:日历时间,是用“从一个标准时间点到此时的时间经过的秒数”来表示的时间。日历时间对于不同的编译器,是不同的。 但是无论你在哪一个时区,在同一时刻对同一个标准时间点来说,日历时间都是一样的。
例如,time_t就是一种日历时间,其值表示从UTC(Coordinated Universal Time)时间1970年1月1日00:00:00(称为UNIX系统的Epoch时间) 到当前时刻的秒数。
这里面涉及了四个类型 : *1.FILETIME:结构持有的64位无符号的文件的日期和时间值。此值表示自UTC(Coordinated Universal Time)时间1601年1月1日开始的100纳秒为单位的时间。 *2.SYSTEMTIME:这个和tm有点类似,代表系统时间。其中,SYSTEMTIME.year的值为多少就表示公元哪一年。 *3.tm:Systemtime-1900得到tm.year,其他的还有些差别 tm.year的值加上1900才表示公元哪一年。 *4.time_t:是日历时间;其值表示从UTC(Coordinated Universal Time)时间1970年1月1日00:00:00(称为UNIX系统的Epoch时间) 到当前时刻的秒数。
FileTime转换为Time_t :
//#### FileTimeToTime_t #### void FileTimeToTime_t( FILETIME ft, time_t *t ) { LONGLONG ll; ULARGE_INTEGER ui; ui.LowPart = ft.dwLowDateTime; ui.HighPart = ft.dwHighDateTime; ll = ft.dwHighDateTime << 32 + ft.dwLowDateTime; //这一步是不是多余的 *t = ((LONGLONG)(ui.QuadPart - 116444736000000000) / 10000000);
//将ui.QuadPart 的数据类型ULONGLONG 强制转换为time_t 的 LONGLONG数据类型 }
//
struct {
DWORD LowPart;
DWORD HighPart;
};
和ULONGLONG QuadPart;组成共用体ULARGE_INTEGER
注释:公元1601年到公元1970年相差369年,转化为秒数即为11644473600 秒。
参见:
Windows API的时间结构体、时间转换及时间获取
如何在C++中将filetime时间转化为字符串?
//********************************************************************/
或是如下方法:
如果编译器中的long类型为4字节时,则 time_t(typedef time_t __int64) 和
filetime( filetime 结构体中有两个unsigned long类型的变量)占用字节大小一样(__int64 是有符号吧),则filetime先可以转化为time_t, 再由time_t转化为tm:
FILETIME是一个__int64。可以这样转化成__int64
filetime st;
__int64 d = * (__int64 * ) & st;
// 因为 filetime 结构体中的两个变量是unsigned long类型的 ,而 *(__int64 *)& st 只是表示将unsigned long类型 的变量st的数据按照__int64 (=longlong)来解释读取而已,并未实际将unsigned long类型 的变量st的数据 转换成__int64 (=longlong) 数据类型格式的。
__int64 d = *(__int64 *)& st;应该改为__int64 d =(__int64) st;不行,因为编译器一般只存在从基本数据 类型到基本数据 类型 的类型转换函数,而像从复合数据 类型到基本数据 类型 等的类型转换函数 一般不存在,即 编译器可能不存在从filetime 结构体 类型到__int64 的类型转换函数。
参见:
中的
为什么filetime 数据类型的变量st可以通过如下方式正确读取其所要表示的数值:
__int64 d = * (__int64 * ) & st?
//
or
//__int64 d2; //memcpy(
&
d2,
&
st,
sizeof
(d2)); (d - 116444736000000000) / 10000000
注释:
上一篇中介绍了C运行库中的时间处理函数。这一篇介绍Windows SDk中提供的时间函数。两种时间系统之间没有本质区别(事实上CRT时间是用Windows时间实现的,当然这是说的VC实现),同样提供本地时间和UTC时间之间的转换。不过,
CRT中的tm时间在SDK中对应为系统时间(SYSTEMTIME),CRT中的time_t时间在SDK中对应的为文件时间(FILETIME),
那个"特殊时刻"也变成1601年1月1日的子夜。
参见:
filetime 转化为 time_t 百度
filetime 时间单位 百度
time_t 时间单位 百度
附加:
补习一下时间单位(http://blog.vckbase.com/zaboli/archive/2005/06/29/8969.aspx )
1ms (毫秒)
1毫秒=0.001秒=10-3秒(millisecond)
1μs (微秒)
1微秒=0.000001=10-6秒(microsecond)
1ns (纳秒)
1纳秒=0.000000001秒=10-9秒(nanosecond )
1ps (皮秒)
1皮秒=0.000000000001秒=10-12秒
1fs (飞秒)
1飞秒=0.00000000000001秒=10-15秒
FILETIME
1功能
FILETIME结构持有的64位无符号的文件的日期和时间值。此值表示自1601年1月1日开始的100纳秒为单位的时间。
2 语法
typedef struct _FILETIME {
DWORD dwLowDateTime; /* 低 32 位 */
DWORD dwHighDateTime; /* 高 32 位 */
} FILETIME, *PFILETIME, *LPFILETIME;
3 成员
dwLowDateTime
低位32位的文件的时间值。
dwHighDateTime
高位32位的文件的时间值。
4 要求
FILETIME是一个__int64。可以这样转化成__int64
__int64 d
=
*
(__int64
*
)
&
st;
//
or
__int64 d2; memcpy(
&
d2,
&
st,
sizeof
(d2));
转化为__int64是一个以100纳秒为单位的值
参考:
FILETIME, SYSTEMTIME 与 time_t 相互转换
//************************************************************ //FILETIME, SYSTEMTIME 与 time_t 相互转换
//#####SYSTEMTIME 与 FILETIME相互转换##### //可以使用系统函数 //FileTimeToSystemTime(&ftcreate,&stcreate);
//参数: //(lpFileTime As FILETIME, lpSystemTime As SYSTEMTIME) //说明 //根据一个FILETIME结构的内容,装载一个SYSTEMTIME结构 //返回值 //Long,非零表示成功,零表示失败。会设置GetLastError //参数表 //参数 类型及说明 //lpFileTime FILETIME,包含了文件时间的一个结构 //lpSystemTime SYSTEMTIME,用于装载系统时间信息的一个结构
//#####SYSTEMTIME 与 time_t相互转换#####
//#### Time_tToSystemTime #### void TimetToSystemTime( time_t t, LPSYSTEMTIME pst ) { FILETIME ft; LONGLONG ll = Int32x32To64(t, 10000000) + 116444736000000000; ft.dwLowDateTime = (DWORD) ll; ft.dwHighDateTime = (DWORD)(ll >> 32); FileTimeToSystemTime( &ft, pst ); }
//#### SystemTimeToTime_t #### void SystemTimeToTime_t( SYSTEMTIME st, time_t *pt ) { FILETIME ft; SystemTimeToFileTime( &st, &ft ); LONGLONG ll; ULARGE_INTEGER ui; ui.LowPart = ft.dwLowDateTime; ui.HighPart = ft.dwHighDateTime; ll = (ft.dwHighDateTime << 32) + ft.dwLowDateTime; *pt = (DWORD)((LONGLONG)(ui.QuadPart - 116444736000000000) / 10000000); }
//#### FileTimeToTime_t #### void FileTimeToTime_t( FILETIME ft, time_t *t ) { LONGLONG ll; ULARGE_INTEGER ui; ui.LowPart = ft.dwLowDateTime; ui.HighPart = ft.dwHighDateTime; ll = ft.dwHighDateTime << 32 + ft.dwLowDateTime; //这一步是不是多余的 *t = ((LONGLONG)(ui.QuadPart - 116444736000000000) / 10000000);
//将ui.QuadPart 的数据类型ULONGLONG 强制转换为time_t 的 LONGLONG数据类型
}
//
struct {
DWORD LowPart;
DWORD HighPart;
};
和ULONGLONG QuadPart;组成共用体ULARGE_INTEGER
//********************************************************************/
参见:
这一篇介绍Windows SDk中提供的时间函数。两种时间系统之间没有本质区别(事实上CRT时间是用Windows时间实现的,当然这是说的VC实现),同样提供本地时间和UTC时间之间的转换。不过CRT中的tm时间在SDK中对应为系统时间(SYSTEMTIME),CRT中的time_t时间在SDK中对应的为文件时间(FILETIME),那个"特殊时刻"也变成1601年1月1日的子夜。
当然,首先要弄清楚FILETIME与SYSTEMTIME定义。
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;
比较一下,很明显,FILETIME与time_t类似,是64位整型,不过FILETIME是以100纳秒(ns)为单位。SYSTEMTIME与tm类似,不过多了一项wMilliseconds。可以看出,SDK时间比CRT的时间提供了更高的精度。同时SDK提供了更丰富的函数来处理时间。
void GetSystemTime(
LPSYSTEMTIME lpSystemTime);
void GetLocalTime(
LPSYSTEMTIME lpSystemTime);
这两个函数获得SYSTEMTIME形式的当前时间,不过GetSystemTime函数获得当前的UTC时间,GetLocalTime获得当前的本地时间,可以想象,获得的两个时间存在着时差。类似于CRT中提供tm与time_t之间的转换,SDK也提供了两个函数来转换SYSTEMTIME时间与FILETIME时间。
BOOL SystemTimeToFileTime(
const SYSTEMTIME* lpSystemTime,
LPFILETIME lpFileTime);
BOOL FileTimeToSystemTime(
const FILETIME* lpFileTime,
LPSYSTEMTIME lpSystemTime);
函数命名很self-explanatory,就不用多说了吧。
SDK还提供了两个很有趣的函数。
BOOL LocalFileTimeToFileTime(
const FILETIME* lpLocalFileTime,
LPFILETIME lpFileTime);
BOOL FileTimeToLocalFileTime(
const FILETIME* lpFileTime,
LPFILETIME lpLocalFileTime);
LocalFileTimeToFileTime函数将本地的FILETIME时间转换为对应的UTC的FILETIME时间。我觉得,这个函数只是通过将本地时间减去与UTC时间的时间差来实现转换,比如在东八区的本地时间转换为对应的UTC时间,只需要将本地时间减去8*60*60*1000*1000*10(单位100ns)。类似,FileTimeToLocalFileTime函数是将UTC时间转换为本地时间,它只是将减去时间差换成加上时间差。
了解了这些功能,让我们用代码说话吧。
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <windows.h>
int main()
{
SYSTEMTIME stLocal, stUTC, stUTC2;
FILETIME ftLocal, ftUTC, ft;
ULARGE_INTEGER uli;
GetLocalTime(&stLocal);
GetSystemTime(&stUTC);
printf("Local System Time(YYYY-MM-DD HH:MM:SS): %d-%d-%d %d:%d:%d/n" , stLocal.wYear, stLocal.wMonth,
stLocal.wDay, stLocal.wHour, stLocal.wMinute, stLocal.wSecond);
printf("UTC System Time (YYYY-MM-DD HH:MM:SS): %d-%d-%d %d:%d:%d/n" , stUTC.wYear, stUTC.wMonth,
stUTC.wDay, stUTC.wHour, stUTC.wMinute, stUTC.wSecond);
SystemTimeToFileTime(&stLocal, &ftLocal);
uli.LowPart = ftLocal.dwLowDateTime;
uli.HighPart = ftLocal.dwHighDateTime;
printf("Local File Time: %llu/n" , uli.QuadPart);
LocalFileTimeToFileTime(&ftLocal, &ftUTC);
uli.LowPart = ftUTC.dwLowDateTime;
uli.HighPart = ftUTC.dwHighDateTime;
printf("UTC File Time: %llu/n" , uli.QuadPart);
FileTimeToSystemTime(&ftUTC, &stUTC2);
printf("UTC System Time2 (YYYY-MM-DD HH:MM:SS): %d-%d-%d %d:%d:%d/n" , stUTC2.wYear, stUTC2.wMonth,
stUTC2.wDay, stUTC2.wHour, stUTC2.wMinute, stUTC2.wSecond);
return EXIT_SUCCESS;
}
程序输出结果如下:
代码13行GetLocalTime函数获得当前的本地SYSTEMTIME时间,14行获得对应的UTC的SYSTEMTIME时间,如输出结果前两行所显示,两者相差8小时(凌晨还在写博客,表扬下自己。。。)。
20行SystemTimeToFileTime函数将本地SYSTEMTIME时间转换为方便计算的本地FILETIME形式时间,如输出结果第三行所显示。
25行LocalFileTimeToFileTime函数将本地FileTime时间转换为对应的UTC的FILETIME时间,如输出结果第四行所显示。就像前面介绍的,如果你将输出结果第三,四两行所显示的数字相减,并除以10*1000*1000*60*60,你将会得出8,你可以算下试试,记住FILETIME是以100纳秒为单位的。
最后30行FileTimeToSystemTime将FILETIME时间转换为SYSTEMTIME时间。可以看出输出结果中第五行与第二行相同,这是必须的,因为两者都是当前本地时间对应的UTC时间。
时间处理时实际项目中经常碰到的问题,这里介绍最常用的时间处理函数。
首先介绍基本的时间概念。时间一般分为两种,一种是本地时间(Local Time),一种是协调世界时间(Coordinated Universal Time ,UTC),也就是传说中的格林威治时间。本地时间与UTC时间之间的差即为时差,比如,北京时间(东八区)比UTC时间晚8个小时。
C运行库中处理时间的函数主要是这四个:
time_t time(
time_t *timer);
time_t类型为32位或64位整型,具体类型由编译系统决定。此函数用来获得从1970年1月1日子夜(这个时刻在不同的CRT实现中可能会不一样)到当前时刻以来所流逝的时间,以秒为单位。这个时间差叫做日历时间(Calendar Time )。
这是当然让我困惑的地方:这个特殊的时刻——1970年1月1日零时零分零秒——是指本地时间呢,还是UTC时间呢?我认为是本地时间,也就是各个时区自己的1970年1月1日零时零分零秒。可以设想这样一种情况,如果全球24时区各有一台电脑,都依次在自己所在时区的本地时间1970年1月1日零时1分零秒调用time函数,那么返回值都是60。注意,这里是依次调用(事实上是每隔1小时),而不是想象中的同时调用,这是因为相邻时区的同一本地时间,总是相差1小时。
当然,time_t型的时间方便计算机处理,但普通用户无法理解这种数字。所以我们通常需要将time_t型时间转换成我们平常所见的年月日形式。CRT中为此定义了tm结构。
struct tm {
int tm_sec; /* seconds after the minute - [0,59] */
int tm_min; /* minutes after the hour - [0,59] */
int tm_hour; /* hours since midnight - [0,23] */
int tm_mday; /* day of the month - [1,31] */
int tm_mon; /* months since January - [0,11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday - [0,6] */
int tm_yday; /* days since January 1 - [0,365] */
int tm_isdst; /* daylight savings time flag */
};
注释中已详细解释了各个字段的用法。显然这个结构中的字段对用户更有意义。我们通常用localtime_s函数将time_t时间转换为tm时间。
errno_t localtime_s(
struct tm * _tm,
const time_t *time);
其中第二个参数为传入的time_t时间,第一个参数为返回的tm时间。由函数名可看出,返回的tm时间表示的是本地时间。当然,我们有时候也需要获得对应的UTC时间,这时我们需要gmtime函数。
errno_t gmtime_s(
struct tm * _tm,
const time_t * time);
后面我们会看到两者的区别。
我们知道了如何将time_t时间转换为tm时间。同样,我们会需要将tm表示的时间转换为time_t时间。这时我们需要mktime函数。
time_t mktime(
struct tm *timeptr);
此函数返回从"特殊时刻"到参数表示的时刻之间流逝的日历时间。另外还有个很好用的特性,就是它能修正传进来的tm结构中各字段的取值范围。比如,如果你将tm.tm_mon设为1,tm.tm_day设为33,然后以其为参数调用mktime函数,此函数会将tm.tm_mon修正为2,tm.tm_day修正为2。具体用法参照MSDN。
我们来分析下面示例代码:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main()
{
struct tm tmLocal, tmUTC;
time_t tNow;
//Get current calendar time
time(&tNow);
printf("Time Now from time(): %llu/n" , tNow);
//Get current local time
localtime_s(&tmLocal, &tNow);
printf("Local Time(YYYY-MM-DD HH:MM:SS): %d-%d-%d %d:%d:%d/n" , tmLocal.tm_year + 1900, tmLocal.tm_mon,
tmLocal.tm_mday, tmLocal.tm_hour, tmLocal.tm_min, tmLocal.tm_sec);
//Get UTC time corresponding to current local time, and tmLocal.tm_hour - tmUTC.tm_hour = 8
gmtime_s(&tmUTC, &tNow);
printf("UTC Time (YYYY-MM-DD HH:MM:SS): %d-%d-%d %d:%d:%d/n" , tmUTC.tm_year + 1900, tmUTC.tm_mon,
tmUTC.tm_mday, tmUTC.tm_hour, tmUTC.tm_min, tmUTC.tm_sec);
//convert tmLocal to calendar time
tNow = mktime(&tmLocal);
printf("Time Now from mktime(): %llu/n" , tNow);
return EXIT_SUCCESS;
}
输出结果如下:
上面代码中,11行time函数获得从"特殊时刻"到当前时刻的日历时间,如输出结果中的第一行显示的1267192581秒。
14行localtime_s函数将日历时间转换为本地tm时间,如输出结果第二行。
18行gmtime_s函数将将日历时间转换为对应的UTC的tm时间,如输出结果第三行显示。很容易看出,第二,三行输出的时间相差8小时,因为我在东八区。如果你修改自己电脑的时区(在控制面板的Date and Time中修改),再运行此程序,比较两次的运行结果,你就可以更好的理解了。
22行mktime函数将tm时间转换为日历时间,输出结果中第四行显示的结果与第一行一样,这是必须的。。。
TimeConvert.h
// TimeConvert.h: interface for the TimeConvert class.
//
//@anthor:TT
//@time:2012.11.22
//@introduction:今天由于处理一个时间,搞得焦头烂额,于是乎打算封装一个转换类,方便自己以后使用,
/*先说个概念:
Coordinated Universal Time(UTC):又称为世界标准时间;时间1970年1月1日00:00:00(称为UNIX系统的Epoch时间)到当前时刻的秒数。
比如,中国内地的时间与UTC的时差为+8,也就是UTC+8。
Calendar Time:日历时间,是用“从一个标准时间点到此时的时间经过的秒数”来表示的时间。对于不同的编译器,是不同的。
但是无论你在哪一个时区,在同一时刻对同一个标准时间点来说,日历时间都是一样的。
*/
//这里面涉及了三个类型
/*
*1.FILETIME:结构持有的64位无符号的文件的日期和时间值。此值表示自1601年1月1日开始的100纳秒为单位的时间。
*2.SYSTEMTIME:这个和tm有点类似,代表系统时间
*3.tm:Systemtime-1900得到tm.year,其他的还有些差别
*4.time_t:是日历时间;其值表示从CUT(Coordinated Universal Time)时间1970年1月1日00:00:00(称为UNIX系统的Epoch时间)
*到当前时刻的秒数。
*/
//
#if !defined(AFX_TIMECONVERT_H__87F35906_DBD6_46F1_BF78_2FA34FCB8409__INCLUDED_)
#define AFX_TIMECONVERT_H__87F35906_DBD6_46F1_BF78_2FA34FCB8409__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <time.h>
#include<olectl.h.>
class TimeConvert
{
public :
static void SystemTimeToFileTime( const SYSTEMTIME*pst,FILETIME *pft);
static void Time_tToFileName( time_t t,FILETIME *ft);
static void TmToTime_t( tm &_t, time_t &t);
static void Time_tToTm( time_t t, tm *_t);
static void TmToSystemTime( const tm &t,SYSTEMTIME *st);
static void SystemTimeTOTm( const SYSTEMTIME &st, tm *t);
static void FileTimeToTime_t( const FILETIME *ft, time_t *t);
static void Time_tToSystemTime( time_t t, SYSTEMTIME *pst);
static void FileTimeToSystemTime( const FILETIME *lpFileTime,SYSTEMTIME *lpSystemTime);
static void SystemTimeToTime_T(SYSTEMTIME *st, time_t *pt );
static void FileTimeToTm( const FILETIME *ft, tm *t);
static void TmToFileTime( tm &t,FILETIME *ft);
static void TimeFormat( char *dest, int length, const char *format, const tm *t);
private :
TimeConvert();
virtual ~TimeConvert();
};
#endif // !defined(AFX_TIMECONVERT_H__87F35906_DBD6_46F1_BF78_2FA34FCB8409__INCLUDED_)
TimeConvert.cpp
// TimeConvert.cpp: implementation of the TimeConvert class.
//
//
#include "TimeConvert.h"
//
// Construction/Destruction
//
TimeConvert::TimeConvert()
{
}
TimeConvert::~TimeConvert()
{
}
void TimeConvert::FileTimeToSystemTime( const FILETIME *lpFileTime,SYSTEMTIME *lpSystemTime)
{
::FileTimeToSystemTime(lpFileTime,lpSystemTime);
}
void TimeConvert::Time_tToSystemTime( time_t t, SYSTEMTIME *pst )
{
// FILETIME ft;
// Time_tToFileName(t,&ft);
// FileTimeToSystemTime( &ft, pst );
//另一种实现
tm *m=localtime(&t);
TmToSystemTime(*m,pst);
}
void TimeConvert::SystemTimeToTime_T(SYSTEMTIME *st, time_t *pt )
{
FILETIME ft;
SystemTimeToFileTime( st, &ft);
FileTimeToTime_t(&ft,pt);
}
void TimeConvert::FileTimeToTime_t( const FILETIME *ft, time_t *t)
{
LONGLONG ll;
ULARGE_INTEGER ui;
ui.LowPart=ft->dwLowDateTime;
ui.HighPart=ft->dwHighDateTime;
ll=(ft->dwHighDateTime<<32)+ft->dwLowDateTime;
*t=(DWORD )(( LONGLONG )(ui.QuadPart- 116444736000000000) /10000000);
}
void TimeConvert::SystemTimeTOTm( const SYSTEMTIME &st, tm *t)
{
tm gm= {st.wSecond, st.wMinute, st.wHour, st.wDay, st.wMonth-1, st.wYear-1900, st.wDayOfWeek, 0, 0};
memcpy(t,&gm,sizeof ( tm ));
}
void TimeConvert::TmToSystemTime( const tm &t,SYSTEMTIME *st)
{
SYSTEMTIME s={1900 + t.tm_year,1 + t.tm_mon,t.tm_wday,t.tm_mday,t.tm_hour,t.tm_min,t.tm_sec,0};
memcpy(st,&s,sizeof (SYSTEMTIME));
}
void TimeConvert::Time_tToTm( time_t t, tm *_t)
{
tm *tt=localtime(&t);
memcpy(_t,tt,sizeof ( tm ));
}
void TimeConvert::TmToTime_t( tm &_t, time_t &t)
{
t=mktime(&_t);
}
void TimeConvert::Time_tToFileName( time_t t,FILETIME *ft)
{
LONGLONG ll = Int32x32To64(t, 10000000) + 116444736000000000;
ft->dwLowDateTime = (DWORD ) ll;
ft->dwHighDateTime = (DWORD )(ll >> 32);
}
void TimeConvert::FileTimeToTm( const FILETIME *ft, tm *t)
{
time_t tm ;
FileTimeToTime_t(ft,&tm );
Time_tToTm(tm ,t);
}
void TimeConvert::TmToFileTime( tm &t,FILETIME *ft)
{
time_t tm ;
TmToTime_t(t,tm );
Time_tToFileName(tm ,ft);
}
void TimeConvert::SystemTimeToFileTime( const SYSTEMTIME*pst,FILETIME *pft )
{
::SystemTimeToFileTime(pst,pft);
}
void TimeConvert::TimeFormat( char *dest, int length, const char *format, const tm *t) //@param:length 为dest长度-1
{
strftime(dest,length,format,t);
}
/*
这关系太TMD乱了吧.....晕了
后记总结:
systemtime与filetime可以通过函数直接转化:FileTimeToSystemTime 和SystemTimeToFileName;
tm和time_t也可以直接转化:localtime()和mktime();
其他转化需要通过中间步骤
Sytemtime和tm有些类似,可以通过加减转化(PS:画个图之后,更好理解)
*/