Der Unix-Zeitstempel, auch bekannt als Unix-Zeit oder POSIX-Zeit, ist eine Zeitdarstellungsmethode, die als die Gesamtzahl der Sekunden vom 1. Januar 1970 um 00:00:00 Greenwich Mean Time bis zur Gegenwart definiert ist. Unix-Zeitstempel werden nicht nur in Unix-Systemen und Unix-ähnlichen Systemen verwendet, sondern sind auch in vielen anderen Betriebssystemen weit verbreitet.

Gegenwärtig verwendet eine beträchtliche Anzahl von Betriebssystemen 32-Bit-Binärzahlen zur Darstellung der Zeit. Der Unix-Zeitstempel solcher Systeme kann höchstens bis zum 19. Januar 2038 um 03:14:07 Greenwich Mean Time verwendet werden (binär: 01111111 11111111 11111111 11111111). Eine Sekunde später wird die Binärzahl zu 10000000 00000000 00000000 00000000, was einen Überlauffehler verursacht und dazu führt, dass das System die Zeit fälschlich als 20:45:52 am 13. Dezember 1901 interpretiert. Dies kann sehr wahrscheinlich Softwarefehler oder sogar Systemlähmungen verursachen. Systeme, die 64-Bit-Binärzahlen zur Darstellung der Zeit verwenden (die höchstens bis zum 4. Dezember 292,277,026,596 um 15:30:08 Greenwich Mean Time verwendet werden können), werden grundsätzlich nicht auf solche Überlaufprobleme stoßen.

Zunächst wollen wir die damit zusammenhängenden Konzepte der Zeit und die Unterschiede zwischen ihnen verstehen. Die Zeitkonzepte, die wir verstehen müssen, sind:

  • Ortszeit (lokale Zeit)
  • Mittlere Greenwich-Zeit (GMT)
  • Koordinierte Weltzeit (Universal Time Coordinated UTC)

Die Ortszeit versteht sich von selbst und bedarf keiner Erklärung.

Schauen wir uns zunächst die Zeitstandards an:

(1) Universalzeit

Die Universalzeit ist der früheste Zeitstandard. Im Jahr 1884 definierte die internationale Gemeinschaft 1s als 1/8.64×10^4 der durchschnittlichen Länge jedes Tages im Jahr. Das durch diesen Standard gebildete Zeitsystem wird Universalzeit genannt, nämlich UT1. Im Jahr 1972 begann die internationale Gemeinschaft, die Zeitskala der Internationalen Atomzeit zu verwenden. Seitdem wird die Zeit, die den Nullmeridian am alten Greenwich-Observatorium passiert, Universalzeit genannt, nämlich UT2, oder Greenwich Mean Time (GMT), die um periodische Unterschiede in der Erdrotationsgeschwindigkeit korrigierte Universalzeit ist.

(2) Atomzeit

Im Jahr 1967 nutzte man die äußerst regelmäßige Schwingungsperiode von Cäsiumatomen, entwickelte eine hochpräzise Atomuhr und definierte die Zeit, die von 9,192,631,770 Zyklen der Strahlung beim Übergang zwischen den Energieniveaus von Cäsiumatomen eingenommen wird, als 1s. Die heute verwendete Zeit ist die im Oktober 1971 definierte Internationale Atomzeit, eine einheitliche Atomzeit, die durch den Vergleich von etwa 200 Atomuhren auf der ganzen Welt und anschließende Datenverarbeitung durch die Zeitabteilung des Internationalen Büros für Maß und Gewicht gewonnen wird, abgekürzt TAI.

(3) Koordinierte Weltzeit

Die Koordinierte Weltzeit ist ein Zeitstandard, der auf der Erdrotation basiert. Da die Rotationsgeschwindigkeit der Erde nicht gleichmäßig ist, hat nicht jeder Tag genau 86400 atomare Sekunden, was zu einem Fehler von 1 Sekunde alle 18 Monate zwischen Rotationszeit und Universal Time führt. Um diesen Fehler zu korrigieren, passt der Internationale Erdrotationsdienst die Greenwich Mean Time an, indem er Schaltsekunden gemäß der tatsächlichen Situation der Erdrotation addiert oder subtrahiert, und veröffentlicht die Standardzeit gemeinsam mit der Zeitabteilung des Internationalen Büros für Maß und Gewicht an die Welt. Dies ist die sogenannte Koordinierte Weltzeit (UTC:CoordinatdeUniversalTime). UTC wird dargestellt als: Jahr (y), Monat (m), Tag (d), Stunde (h), Minute (min), Sekunde (s), alle in Zahlen ausgedrückt.

Im GPS-System gibt es zwei Arten von Zeit, eine ist UTC und die andere ist LT (Ortszeit). Der Unterschied zwischen ihnen ist die Zeitzone. UTC ist die Zeit in Zeitzone 0, und die Ortszeit ist die lokale Zeit. Wenn es beispielsweise in Peking 8:00 Uhr morgens ist (UTC+8), dann ist die UTC-Zeit 0:00, also acht Stunden hinter der Pekinger Zeit. Mit dieser Berechnung können wir aus dem obigen Verständnis die Greenwich Mean Time als Koordinierte Weltzeit (GMT=UTC) betrachten. Sowohl Greenwich Mean Time als auch UTC-Zeit werden in Sekunden berechnet.

In unserer täglichen Arbeit werden die meisten in Computerprotokollen geschriebenen Zeiten mit UTC-Zeit berechnet. Wie sollten wir also UTC-Zeit in Ortszeit umrechnen, um Protokolle leichter anzeigen zu können? Und wie sollten wir bei der Programmentwicklung Ortszeit in UTC-Zeit umrechnen?

Im Folgenden wird ein einfaches und praktisches Werkzeug vorgestellt, nämlich die Verwendung des linux/unix-Befehls date zur Umrechnung zwischen Ortszeit und UTC-Zeit.

Wie allgemein bekannt ist, wird die in einem Computer angezeigte UTC-Zeit in Sekunden seit (1. Januar 1970 0:00:00) gezählt. Die UTC-Zeit, die Sie sehen, ist genau die Anzahl der Sekunden von diesem Zeitpunkt im Jahr 1970 bis zum konkreten Zeitpunkt.

In der Programmierung verwenden wir oft die Zeit, zum Beispiel, um die Systemzeit abzurufen (das Jahr, den Monat, den Tag, die Stunde, die Minute, die Sekunde, den Wochentag usw. des Systems zu erhalten) oder um etwas nach einem Intervall zu tun; dann verwenden wir einige Zeitfunktionen.

Unter Linux gibt es zwei übliche Möglichkeiten, die Zeit zu speichern: Eine ist die Anzahl der Sekunden, die von 1970 bis jetzt vergangen sind, und die andere ist die Verwendung einer Struktur, um Jahr, Monat, Tag, Stunde, Minute und Sekunde getrennt zu speichern.

Der Typ time_t wird verwendet, um zu speichern, wie viele Sekunden von 1970 bis jetzt vergangen sind. Genauer gesagt kann man die Struktur struct timeval verwenden, die auf Mikrosekunden genau ist.

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

Diejenige, die Jahr, Monat und Tag direkt speichert, ist eine Struktur:

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; /*日光节约时间的旗标*/
};

Besondere Aufmerksamkeit ist erforderlich: Das Jahr gibt an, wie viele Jahre seit 1900 vergangen sind, nicht direkt gespeichert als z. B. 2011; der Monat beginnt bei 0, 0 bedeutet Januar; der Wochentag beginnt ebenfalls bei 0, 0 bedeutet Sonntag, 1 bedeutet Montag.

Im Folgenden stellen wir die Zeitfunktionen vor, die wir üblicherweise verwenden:

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

Wandelt die Informationen in der Struktur in reale Zeit um und zeigt sie als Zeichenkette an.

char *ctime(const time_t *timep);

Wandelt timep in reale Zeit um, angezeigt als Zeichenkette. Der Unterschied zu asctime besteht darin, dass die Form des übergebenen Parameters anders ist.

double difftime(time_t time1, time_t time2);

Gibt die Differenz in Sekunden zwischen zwei Zeiten zurück.

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

Gibt die Anzahl der Sekunden und Mikrosekunden von 1970 bis zur aktuellen Zeit zurück. Das folgende tz ist die Zeitzone und wird im Allgemeinen nicht verwendet.

struct tm* gmtime(const time_t *timep);

Wandelt die durch time_t dargestellte Zeit in UTC-Zeit ohne Zeitzonenumrechnung um. Es ist ein Zeiger auf die Struktur struct tm.

stuct tm* localtime(const time_t *timep);

Ähnlich wie gmtime, aber es ist eine Zeit, die eine Zeitzonenumrechnung durchlaufen hat.

time_t mktime(struct tm* timeptr);

Konvertieren Sie die Zeit in einer struct tm-Struktur in die Anzahl der Sekunden seit 1970 bis zur Gegenwart.

time_t time(time_t *t);

Ermitteln Sie die Anzahl der Sekunden vom 1. Januar 1970 bis zur Gegenwart.

Das Obige ist eine kurze Einführung. Sehen wir uns unten die Verwendung dieser Funktionen in der Praxis an:

/*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;
}

Kompilieren und ausführen:

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

Im Folgenden wird der Typ time_t direkt in unser gängiges Format umgewandelt:

/* 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;
}

Kompilieren und ausführen:

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

Ich habe ein Buch gelesen, in dem stand, dass, wenn diese beiden Beispiele nacheinander ausgeführt werden, die Ergebnisse der beiden bis auf eine Sekundendifferenz gleich sein sollten (die Ausführung des Programms dauert Zeit). Als ich es hier jedoch ausführte, stellte ich fest, dass sie sich um eine lange Zeitspanne unterschieden: das eine war Freitag, das andere Samstag. Später habe ich einmal den Befehl date ausgeführt.

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

Ich habe festgestellt, dass date und gettime2 ziemlich konsistent sind. Ich vermute, dass gettime1 wahrscheinlich keine Zeitzonenumrechnung durchlaufen hat; es gibt einen Unterschied zwischen ihnen.

/*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;
}

Kompilieren und ausführen:

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

Dieses Zeitergebnis stimmt mit gettime1 überein.

/*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;
}

Kompilieren und ausführen:

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

Aus den obigen Ergebnissen können wir Folgendes sagen:

Die von time, gmtime und asctime dargestellten Zeiten sind alle UTC-Zeiten, nur mit unterschiedlichen Datentypen.

Die von localtime und ctime dargestellten Zeiten sind alle Zeiten nach der Zeitzonenumrechnung und sollten mit der CST-Zeit übereinstimmen, die vom Systembefehl date angezeigt wird.

/*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;
}

Kompilieren und ausführen:

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

Hier wird UTC-Zeit in lokale Zeit umgewandelt und dann lokale Zeit in UTC-Zeit. Die Konvertierungsergebnisse bleiben konsistent.

/*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;
}

Kompilieren und ausführen:

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

Daran ist zu erkennen, dass die Zeiten nach der Umwandlung inkonsistent sind. Rechnet man nach, beträgt die Differenz genau 8 Stunden ((1200075192-1200046392)/3600 = 8). Das zeigt, dass mktime Ortszeit in UTC-Zeit umwandelt. Die Zeit hier war ursprünglich UTC-Zeit, daher weicht das Ergebnis nach einer weiteren Zeitzonenumwandlung um 8 Stunden ab. Man sollte bei der Verwendung vorsichtig sein.

Die Funktion strftime() formatiert Zeit.

Wir können die Funktion strftime() verwenden, um die Zeit in das gewünschte Format zu formatieren. Ihr Prototyp lautet wie folgt:

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

Wir können die in timeptr gespeicherten Zeitinformationen entsprechend den Formatbefehlen in der Zeichenkette, auf die format zeigt, in die Zeichenkette, auf die strDest zeigt, schreiben, wobei höchstens maxsize Zeichen in strDest gespeichert werden. Diese Funktion gibt die Anzahl der Zeichen zurück, die in die Zeichenkette, auf die strDest zeigt, geschrieben wurden.

Die Arbeitsweise von strftime() ähnelt etwas der von sprintf(): Sie erkennt eine Reihe von Formatbefehlen, die mit einem Prozentzeichen (%) beginnen, und die formatierte Ausgabe wird in einer Zeichenkette abgelegt. Die Formatbefehle legen die genaue Darstellung verschiedener Datums- und Zeitinformationen in strDest fest. Andere Zeichen in der Formatzeichenkette werden unverändert in die Zeichenkette übernommen. Die Formatbefehle sind unten aufgeführt und es wird zwischen Groß- und Kleinschreibung unterschieden.

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

Wenn Sie die aktuelle Uhrzeit im 12-Stunden-Format anzeigen möchten, wie im folgenden Programm:

#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;
}

Das Ausführungsergebnis lautet:

It is now 4PM

Das folgende Programm zeigt das aktuelle vollständige Datum an:

#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;
}

Quelladresse: http://blog.csdn.net/love_gaohz/article/details/6637625