Unix timestamp, also known as Unix time or POSIX time, is a time representation method defined as the total number of seconds from 00:00:00 on January 1, 1970 Greenwich Mean Time to the present. Unix timestamps are not only used in Unix systems and Unix-like systems, but are also widely adopted in many other operating systems.

At present, a considerable number of operating systems use 32-bit binary numbers to represent time. The Unix timestamp of such systems can be used at most until 03:14:07 on January 19, 2038 Greenwich Mean Time (binary: 01111111 11111111 11111111 11111111). One second later, the binary number becomes 10000000 00000000 00000000 00000000, causing an overflow error, causing the system to misinterpret the time as 20:45:52 on December 13, 1901. This is very likely to cause software failures, or even system paralysis. Systems that use 64-bit binary numbers to represent time (which can be used at most until 15:30:08 on December 4, 292,277,026,596 Greenwich Mean Time) will basically not encounter such overflow problems.

First, let's understand the related concepts of time and the differences between them. The time concepts we need to understand are:

  • Local time (locale time)
  • Greenwich Mean Time (GMT)
  • Coordinated Universal Time (Universal Time Coordinated UTC)

Local time, it goes without saying and needs no explanation.

First, let's look at the standards of time:

(1) Universal Time

Universal Time is the earliest time standard. In 1884, the international community defined 1s as 1/8.64×10^4 of the average length of each day throughout the year. The time system formed by this standard is called Universal Time, namely UT1. In 1972, the international community began to use the International Atomic Time scale. Since then, the time passing the Prime Meridian at the old Greenwich Observatory has been called Universal Time, namely UT2, or Greenwich Mean Time (GMT), which is Universal Time corrected for periodic differences in the Earth's rotation speed.

(2) Atomic Time

In 1967, taking advantage of the extremely regular oscillation period of cesium atoms, people developed a high-precision atomic clock and defined the time occupied by 9,192,631,770 cycles of cesium atom energy-level transition radiation as 1s. The time used now is the International Atomic Time defined in October 1971, which is a unified atomic time obtained by comparing about 200 atomic clocks around the world and then performing data processing by the time department of the International Bureau of Weights and Measures, abbreviated as TAI.

(3) Coordinated Universal Time

Coordinated Universal Time is a time standard based on the Earth's rotation. Because the Earth's rotation speed is not uniform, not every day is exactly 86400 atomic seconds, resulting in an error of 1 second every 18 months between rotation time and Universal Time. To correct this error, the International Earth Rotation Service adjusts Greenwich Mean Time by adding or subtracting leap seconds according to the actual situation of the Earth's rotation, and jointly releases the standard time to the world with the time department of the International Bureau of Weights and Measures. This is the so-called Coordinated Universal Time (UTC:CoordinatdeUniversalTime). UTC is represented as: year (y), month (m), day (d), hour (h), minute (min), second (s), all expressed in numbers.

In the GPS system, there are two types of time, one is UTC and the other is LT (local time). The difference between them is the time zone. UTC is the time in time zone 0, and local time is the local time. For example, if Beijing is 8:00 AM (UTC+8), then UTC time is 0:00, which is eight hours behind Beijing time. With this calculation, from the above understanding, we can consider Greenwich Mean Time to be Coordinated Universal Time (GMT=UTC). Both Greenwich Mean Time and UTC time are calculated in seconds.

In our daily work, most of the times written in computer logs are calculated using UTC time. So how should we convert UTC time to local time for easier log viewing? And when doing program development, how should we convert local time to UTC time?

The following introduces a simple and practical tool, which is using the linux/unix command date to convert between local time and UTC time.

As everyone knows, the UTC time seen in a computer is counted in seconds from (January 1, 1970 0:00:00). The UTC time you see is exactly how many seconds from this point in 1970 to the specific time.

In programming, we may often use time, for example, to get the system time (obtain the system's year, month, day, hour, minute, second, weekday, etc.), or to do something after an interval, then we use some time functions.

Under Linux, there are two common ways to store time: one is the number of seconds elapsed from 1970 to now, and the other is using a structure to store year, month, day, hour, minute, second separately.

The type time_t is used to store how many seconds have elapsed from 1970 to now. To be more precise, you can use the structure struct timeval, which is accurate to microseconds.

struct timeval
{
    long tv_sec; /*秒*/
    long tv_usec; /*微秒*/
};

The one that directly stores year, month, day is a structure:

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;  /*月, 从一月算起,0-11*/  1+p->tm_mon;
    int tm_year;  /*年, 从1900至今已经多少年*/  1900+ p->tm_year;
    int tm_wday; /*星期,一周中的第几天, 从星期日算起,0-6*/
    int tm_yday; /*从今年1月1日到目前的天数,范围0-365*/
    int tm_isdst; /*日光节约时间的旗标*/
};

Special attention is needed: the year is how many years since 1900, not directly stored as e.g. 2011; the month starts from 0, 0 means January; the weekday also starts from 0, 0 means Sunday, 1 means Monday.

Below we introduce the time functions we commonly use:

#include <time.h>
char *asctime(const struct tm* timeptr);

Convert the information in the structure to real-world time and display it as a string.

char *ctime(const time_t *timep);

Convert timep to real-world time, displayed as a string. The difference from asctime is that the form of the passed parameter is different.

double difftime(time_t time1, time_t time2);

Return the number of seconds difference between two times.

int gettimeofday(struct timeval *tv, struct timezone *tz);

Return the number of seconds and microseconds from 1970 to the current time. The following tz is the time zone, generally not used.

struct tm* gmtime(const time_t *timep);

Convert the time represented by time_t to UTC time without time zone conversion. It is a struct tm structure pointer.

stuct tm* localtime(const time_t *timep);

Similar to gmtime, but it is time that has undergone time zone conversion.

time_t mktime(struct tm* timeptr);

Convert the time in a struct tm structure to the number of seconds since 1970 to the present.

time_t time(time_t *t);

Get the number of seconds from January 1, 1970 to the present.

The above is a brief introduction. Let's look at the usage of these functions in practice below:

/*gettime1.c*/
#include <time.h>

int main()
{
    time_t timep;
   
    time(&timep); /*获取time_t类型的当前时间*/
    /*用gmtime将time_t类型的时间转换为struct tm类型的时间按,//没有经过时区转换的UTC时间
      然后再用asctime转换为我们常见的格式 Fri Jan 11 17:25:24 2008
    */
    printf("%s", asctime(gmtime(&timep)));
    return 0;
}

Compile and run:

$gcc -o gettime1 gettime1.c
$./gettime1
Fri Jan 11 17:04:08 2008

Below is to directly convert the time_t type into our common format:

/* gettime2.c*/
#include <time.h>

int main()
{
    time_t timep;
   
    time(&timep); /*获取time_t类型当前时间*/   
    /*转换为常见的字符串:Fri Jan 11 17:04:08 2008*/
    printf("%s", ctime(&timep));
    return 0;
}

Compile and run:

$gcc -o gettime2 gettime2.c
$./gettime2
Sat Jan 12 01:25:29 2008

I read a book that said if these two examples are executed one after another, the results of the two should be the same except for a difference in seconds (executing the program takes time). However, when I ran it here, I found that they differed by a long time: one was Friday, the other Saturday. Later I executed the date command once.

$ date
六 1月 12 01:25:19 CST 2008

I found that date and gettime2 are quite consistent. I estimate that gettime1 probably did not undergo time zone conversion; there is a difference between them.

/*gettime3.c */
#include <time.h>

int main()
{
    char *wday[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    time_t timep;
    struct tm *p;
   
    time(&timep); /*获得time_t结构的时间,UTC时间*/
    p = gmtime(&timep); /*转换为struct tm结构的UTC时间*/
    printf("%d/%d/%d ", 1900 + p->tm_year, 1+ p->tm_mon, p->tm_mday);
    printf("%s %d:%d:%d\n", wday[p->tm_wday], p->tm_hour,
        p->tm_min, p->tm_sec);
    return 0;
}

Compile and run:

$gcc -o gettime3 gettime3.c
$./gettime3
2008/1/11 Fri 17:42:54

From this time result, it is consistent with gettime1.

/*gettime4.c*/
#include <time.h>

int main()
{
    char *wday[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    time_t timep;
    struct tm *p;
   
    time(&timep); /*获得time_t结构的时间,UTC时间*/
    p = localtime(&timep); /*转换为struct tm结构的当地时间*/
    printf("%d/%d/%d ", 1900 + p->tm_year, 1+ p->tm_mon, p->tm_mday);
    printf("%s %d:%d:%d\n", wday[p->tm_wday], p->tm_hour, p->tm_min, p->tm_sec);
    return 0;
}

Compile and run:

$gcc -o gettime4 gettime4.c
$./gettime4
2008/1/12 Sat 1:49:29

From the above results, we can say this:

The times represented by time, gmtime, and asctime are all UTC times, just with different data types.

The times represented by localtime and ctime are all times after time zone conversion, and they should be consistent with the CST time shown by the system command date.

/*gettime5.c*/
#include <time.h>

int main()
{
    time_t timep;
    struct tm *p;

    time(&timep); /*当前time_t类型UTC时间*/
    printf("time():%d\n",timep);
    p = localtime(&timep); /*转换为本地的tm结构的时间按*/
    timep = mktime(p); /*重新转换为time_t类型的UTC时间,这里有一个时区的转换*/ //by lizp 错误,没有时区转换, 将struct tm 结构的时间转换为从1970年至p的秒数
    printf("time()->localtime()->mktime(): %d\n", timep);
    return 0;
}

Compile and run:

$gcc -o gettime5 gettime5.c
$./gettime5
time():1200074913
time()->localtime()->mktime(): 1200074913

Here, UTC time is converted to local time, and then local time is converted to UTC time. The conversion results remain consistent.

/*gettime6.c */
#include <time.h>

int main()
{
    time_t timep;
    struct tm *p;

    time(&timep);  /*得到time_t类型的UTC时间*/
    printf("time():%d\n",timep);
    p = gmtime(&timep); /*得到tm结构的UTC时间*/
    timep = mktime(p); /*转换,这里会有时区的转换*/ //by lizp 错误,没有时区转换, 将struct tm 结构的时间转换为从1970年至p的秒数
    printf("time()->gmtime()->mktime(): %d\n", timep);
    return 0;
}

Compile and run:

$gcc -o gettime6 gettime6.c
$./gettime6
time():1200075192
time()->gmtime()->mktime(): 1200046392

From this we can see that the times are inconsistent after conversion. Calculating, the difference is exactly 8 hours ((1200075192-1200046392)/3600 = 8). This shows that mktime converts local time to UTC time. The time here was originally UTC time, so after another time zone conversion, the result differs by 8 hours. You should be careful when using it.

The strftime() function formats time.

We can use the strftime() function to format time into the format we want. Its prototype is as follows:

size_t strftime(
     char *strDest,
     size_t maxsize,
     const char *format,
     const struct tm *timeptr
);

We can put the time information stored in timeptr into the string pointed to by strDest according to the format commands in the string pointed to by format, storing at most maxsize characters in strDest. This function returns the number of characters placed in the string pointed to by strDest.

The operation of strftime() is somewhat similar to sprintf(): it recognizes a set of format commands beginning with a percent sign (%), and the formatted output is placed in a string. The format commands specify the exact representation of various date and time information in strDest. Other characters in the format string are placed into the string as-is. The format commands are listed below, and they are case-sensitive.

%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 时区名称,如果不能得到时区名称则返回空字符。
%% 百分号

If you want to display what time it is now in 12-hour format, like the following program:

#include "time.h"
#include "stdio.h"
int main(void)
{
    struct tm *ptr;
    time_t lt;
    char str[80];
    lt=time(NULL);
    ptr=localtime(<);
    strftime(str,100,"It is now %I %p",ptr);
    printf(str);
    return 0;
}

Its running result is:

It is now 4PM

The following program displays the current complete date:

#include<stdio.h>
#include<string.h>
#include<time.h>
int main( void )
{
    struct tm *newtime;
    char tmpbuf[128];
    time_t lt1;
   
    time( &lt1 );
    newtime=localtime(&lt1);
   
    strftime( tmpbuf, 128, "Today is %A, day %d of %B in the year %Y.\n", newtime);
    printf(tmpbuf);

    return 0;
}

Source address: http://blog.csdn.net/love_gaohz/article/details/6637625