L'horodatage Unix, également appelé temps Unix ou temps POSIX, est une méthode de représentation du temps définie comme le nombre total de secondes écoulées depuis le 1er janvier 1970 à 00:00:00, heure moyenne de Greenwich, jusqu'à présent. Les horodatages Unix ne sont pas seulement utilisés dans les systèmes Unix et les systèmes de type Unix, mais sont également largement adoptés dans de nombreux autres systèmes d'exploitation.
Actuellement, un nombre considérable de systèmes d'exploitation utilisent des nombres binaires de 32 bits pour représenter le temps. L'horodatage Unix de ces systèmes peut être utilisé au maximum jusqu'au 19 janvier 2038 à 03:14:07, heure moyenne de Greenwich (binaire : 01111111 11111111 11111111 11111111). Une seconde plus tard, le nombre binaire devient 10000000 00000000 00000000 00000000, provoquant une erreur de dépassement de capacité, ce qui amène le système à interpréter erronément le temps comme étant le 13 décembre 1901 à 20:45:52. Cela est très susceptible de provoquer des défaillances logicielles, voire une paralysie du système. Les systèmes qui utilisent des nombres binaires de 64 bits pour représenter le temps (qui peuvent être utilisés au maximum jusqu'au 4 décembre 292,277,026,596 à 15:30:08, heure moyenne de Greenwich) ne rencontreront pratiquement pas de tels problèmes de dépassement de capacité.
Tout d'abord, comprenons les concepts liés au temps et les différences entre eux. Les concepts temporels que nous devons comprendre sont :
- Heure locale (temps local)
- Heure moyenne de Greenwich (GMT)
- Temps universel coordonné (UTC)
Heure locale, cela va sans dire et n'a pas besoin d'explication.
Tout d'abord, examinons les étalons de temps :
(1) Temps universel
Le temps universel est le plus ancien étalon de temps. En 1884, la communauté internationale a défini 1s comme 1/8.64×10^4 de la durée moyenne de chaque jour tout au long de l'année. Le système horaire formé par cet étalon est appelé temps universel, à savoir UT1. En 1972, la communauté internationale a commencé à utiliser l'échelle de temps atomique internationale. Depuis lors, le temps passant par le méridien d'origine de l'ancien observatoire de Greenwich a été appelé temps universel, à savoir UT2, ou Greenwich Mean Time (GMT), qui est le temps universel corrigé des différences périodiques de la vitesse de rotation de la Terre.
(2) Temps atomique
En 1967, en tirant parti de la période d'oscillation extrêmement régulière des atomes de césium, on a mis au point une horloge atomique de haute précision et défini comme 1s la durée occupée par 9,192,631,770 cycles du rayonnement de transition entre niveaux d'énergie de l'atome de césium. Le temps utilisé actuellement est le temps atomique international défini en octobre 1971, qui est un temps atomique unifié obtenu en comparant environ 200 horloges atomiques dans le monde entier, puis en effectuant un traitement de données par le service du temps du Bureau international des poids et mesures, en abrégé TAI.
(3) Temps universel coordonné
Le temps universel coordonné est une norme de temps basée sur la rotation de la Terre. Comme la vitesse de rotation de la Terre n'est pas uniforme, chaque jour n'est pas exactement de 86400 secondes atomiques, ce qui entraîne une erreur de 1 seconde tous les 18 mois entre le temps de rotation et le temps universel. Pour corriger cette erreur, le Service international de la rotation terrestre ajuste le temps moyen de Greenwich en ajoutant ou en soustrayant des secondes intercalaires selon la situation réelle de la rotation de la Terre, et publie conjointement le temps standard au monde avec le département du temps du Bureau international des poids et mesures. C'est ce qu'on appelle le temps universel coordonné (UTC:CoordinatdeUniversalTime). UTC est représenté comme : année (y), mois (m), jour (d), heure (h), minute (min), seconde (s), tous exprimés en chiffres.
Dans le système GPS, il existe deux types de temps, l'un est UTC et l'autre est LT (heure locale). La différence entre eux est le fuseau horaire. UTC est l'heure du fuseau horaire 0, et l'heure locale est l'heure locale. Par exemple, si Pékin est à 8h00 (UTC+8), alors l'heure UTC est 0h00, soit huit heures de retard sur l'heure de Pékin. Avec ce calcul, d'après la compréhension ci-dessus, nous pouvons considérer le temps moyen de Greenwich comme le temps universel coordonné (GMT=UTC). Le temps moyen de Greenwich et l'heure UTC sont tous deux calculés en secondes.
Dans notre travail quotidien, la plupart des heures écrites dans les journaux informatiques sont calculées en utilisant l'heure UTC. Alors comment convertir l'heure UTC en heure locale pour faciliter la consultation des journaux ? Et lors du développement de programmes, comment convertir l'heure locale en heure UTC ?
Ce qui suit présente un outil simple et pratique, à savoir l'utilisation de la commande linux/unix date pour convertir entre l'heure locale et l'heure UTC.
Comme tout le monde le sait, l'heure UTC visible dans un ordinateur est comptée en secondes depuis (1er janvier 1970 0:00:00). L'heure UTC que vous voyez correspond exactement au nombre de secondes écoulées depuis ce point en 1970 jusqu'à l'heure spécifique.
En programmation, nous pouvons souvent utiliser le temps, par exemple pour obtenir l'heure système (obtenir l'année, le mois, le jour, l'heure, la minute, la seconde, le jour de la semaine, etc. du système), ou pour faire quelque chose après un intervalle, alors nous utilisons certaines fonctions de temps.
Sous Linux, il existe deux façons courantes de stocker le temps : l'une est le nombre de secondes écoulées de 1970 jusqu'à maintenant, et l'autre consiste à utiliser une structure pour stocker séparément l'année, le mois, le jour, l'heure, la minute et la seconde.
Le type time_t est utilisé pour stocker combien de secondes se sont écoulées de 1970 à maintenant. Pour être plus précis, vous pouvez utiliser la structure struct timeval, qui est précise à la microseconde près.
struct timeval
{
long tv_sec; /*秒*/
long tv_usec; /*微秒*/
};
Celui qui stocke directement l'année, le mois et le jour est une 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; /*日光节约时间的旗标*/
};
Une attention particulière est nécessaire : l'année correspond au nombre d'années écoulées depuis 1900, et n'est pas stockée directement comme par ex. 2011 ; le mois commence à 0, 0 signifie janvier ; le jour de la semaine commence aussi à 0, 0 signifie dimanche, 1 signifie lundi.
Ci-dessous, nous présentons les fonctions de temps que nous utilisons couramment :
#include <time.h> char *asctime(const struct tm* timeptr);
Convertit les informations contenues dans la structure en heure réelle et les affiche sous forme de chaîne de caractères.
char *ctime(const time_t *timep);
Convertit timep en heure réelle, affichée sous forme de chaîne de caractères. La différence avec asctime est que la forme du paramètre passé est différente.
double difftime(time_t time1, time_t time2);
Renvoie le nombre de secondes d'écart entre deux temps.
int gettimeofday(struct timeval *tv, struct timezone *tz);
Renvoie le nombre de secondes et de microsecondes depuis 1970 jusqu'à l'heure actuelle. Le tz suivant est le fuseau horaire, généralement non utilisé.
struct tm* gmtime(const time_t *timep);
Convertit le temps représenté par time_t en temps UTC sans conversion de fuseau horaire. C'est un pointeur de structure struct tm.
stuct tm* localtime(const time_t *timep);
Similaire à gmtime, mais il s'agit d'un temps qui a subi une conversion de fuseau horaire.
time_t mktime(struct tm* timeptr);
Convertir le temps contenu dans une structure struct tm en nombre de secondes écoulées depuis 1970 jusqu'à présent.
time_t time(time_t *t);
Obtenir le nombre de secondes écoulées depuis le 1er janvier 1970 jusqu'à présent.
Ce qui précède est une brève introduction. Regardons ci-dessous l'utilisation de ces fonctions en pratique :
/*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;
}
Compiler et exécuter :
$gcc -o gettime1 gettime1.c $./gettime1 Fri Jan 11 17:04:08 2008
Ce qui suit consiste à convertir directement le type time_t dans notre format courant :
/* 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;
}
Compiler et exécuter :
$gcc -o gettime2 gettime2.c $./gettime2 Sat Jan 12 01:25:29 2008
J'ai lu un livre qui disait que si ces deux exemples sont exécutés l'un après l'autre, les résultats des deux devraient être identiques, à une différence de quelques secondes près (l'exécution du programme prend du temps). Cependant, lorsque je l'ai exécuté ici, j'ai constaté qu'ils présentaient un écart de temps important : l'un était vendredi, l'autre samedi. Plus tard, j'ai exécuté une fois la commande date.
$ date 六 1月 12 01:25:19 CST 2008
J'ai constaté que date et gettime2 concordent assez bien. J'estime que gettime1 n'a probablement pas subi de conversion de fuseau horaire ; il y a une différence entre eux.
/*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;
}
Compiler et exécuter :
$gcc -o gettime3 gettime3.c $./gettime3 2008/1/11 Fri 17:42:54
D'après ce résultat de temps, il est cohérent avec 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;
}
Compiler et exécuter :
$gcc -o gettime4 gettime4.c $./gettime4 2008/1/12 Sat 1:49:29
D'après les résultats ci-dessus, on peut dire ceci :
Les temps représentés par time, gmtime et asctime sont tous des temps UTC, simplement avec des types de données différents.
Les temps représentés par localtime et ctime sont tous des temps après conversion de fuseau horaire, et ils devraient être cohérents avec l'heure CST affichée par la commande système 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;
}
Compiler et exécuter :
$gcc -o gettime5 gettime5.c $./gettime5 time():1200074913 time()->localtime()->mktime(): 1200074913
Ici, le temps UTC est converti en heure locale, puis l'heure locale est convertie en temps UTC. Les résultats de conversion restent cohérents.
/*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;
}
Compiler et exécuter :
$gcc -o gettime6 gettime6.c $./gettime6 time():1200075192 time()->gmtime()->mktime(): 1200046392
D'après cela, nous pouvons voir que les temps sont incohérents après conversion. En calculant, la différence est exactement de 8 heures ((1200075192-1200046392)/3600 = 8). Cela montre que mktime convertit l'heure locale en heure UTC. L'heure ici était à l'origine en UTC, donc après une autre conversion de fuseau horaire, le résultat diffère de 8 heures. Il faut être prudent lors de son utilisation.
La fonction strftime() formate l'heure.
Nous pouvons utiliser la fonction strftime() pour formater l'heure dans le format souhaité. Son prototype est le suivant :
size_t strftime(
char *strDest,
size_t maxsize,
const char *format,
const struct tm *timeptr
);
Nous pouvons placer les informations de temps stockées dans timeptr dans la chaîne pointée par strDest selon les commandes de format présentes dans la chaîne pointée par format, en stockant au maximum maxsize caractères dans strDest. Cette fonction renvoie le nombre de caractères placés dans la chaîne pointée par strDest.
Le fonctionnement de strftime() est quelque peu similaire à celui de sprintf() : il reconnaît un ensemble de commandes de format commençant par un signe de pourcentage (%), et la sortie formatée est placée dans une chaîne. Les commandes de format spécifient la représentation exacte de diverses informations de date et d'heure dans strDest. Les autres caractères de la chaîne de format sont placés tels quels dans la chaîne. Les commandes de format sont listées ci-dessous, et elles sont sensibles à la casse.
%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 时区名称,如果不能得到时区名称则返回空字符。 %% 百分号
Si vous voulez afficher l'heure qu'il est actuellement au format 12 heures, comme dans le programme suivant :
#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;
}
Son résultat d'exécution est :
It is now 4PM
Le programme suivant affiche la date complète actuelle :
#include<stdio.h>
#include<string.h>
#include<time.h>
int main( void )
{
struct tm *newtime;
char tmpbuf[128];
time_t lt1;
time( <1 );
newtime=localtime(<1);
strftime( tmpbuf, 128, "Today is %A, day %d of %B in the year %Y.\n", newtime);
printf(tmpbuf);
return 0;
}
Adresse source : http://blog.csdn.net/love_gaohz/article/details/6637625