c语言中日期和时间
Every time I need to work with dates and times in C I find myself scrabbling around trying to refresh my memory on how the data structures and functions provided by time.h work. I have therefore put together a short program to demo the most important functionality, mainly as a reference for myself but I hope you find it useful as well.
每当我需要在CI中使用日期和时间时,都会发现自己在尝试刷新有关time.h提供的数据结构和功能如何工作的记忆。 因此,我整理了一个简短的程序来演示最重要的功能,主要是作为给自己的参考,但我希望您也觉得它有用。
Dealing with dates and times is a pain. The units are incredibly messy — not only do we have to deal with the various units being split up in different ways, we have to deal with leap years, daylight saving time, time zones and even the occasional leap second.
处理日期和时间很痛苦。 这些单位非常混乱-我们不仅必须处理以不同方式拆分的各个单位,而且还必须处理we年,夏时制,时区,甚至偶有leap秒。
Fortunately every mainstream language or framework provides us with off-the-shelf functionality for handling dates and times but even these are not entirely straightforward. This is particularly true with C so I thought I would provide myself with a few bits of sample code which I can copy and paste whenever I need, and also share with anybody else who might find it useful.
幸运的是,每种主流语言或框架都为我们提供了用于处理日期和时间的现成功能,但是即使这些也不是完全简单的。 对于C来说尤其如此,因此我想为自己提供一些示例代码,可以在需要时复制和粘贴这些示例代码,并且还可以与其他可能有用的人共享。
时间 (time.h)
The C standard library includes time.h which provides us with a struct and an integer type to represent dates and times. These are combined; there are no separate types for dates and times. This makes sense when you think about it, as the separation between the two is entirely arbitrary and has no real meaning.
C标准库包括time.h ,它为我们提供了一个结构和一个整数类型来表示日期和时间。 这些是结合在一起的。 日期和时间没有单独的类型。 考虑到这一点,这是有道理的,因为两者之间的分隔完全是任意的,没有实际意义。
These are the two types used to represent dates and times.
这是用于表示日期和时间的两种类型。
![Image for post](https://miro.medium.com/max/9999/1*e7wncNYvp0olDMO8SPTf8Q.png)
Of course the two types show above both represent what is essentially the same information, albeit in very different forms. The standard library therefore provides us with functions for obtaining a variable of each type from the other.
当然,以上显示的两种类型都表示本质上相同的信息,尽管形式非常不同。 因此,标准库为我们提供了从彼此获取每种类型的变量的函数。
![Image for post](https://miro.medium.com/max/9999/1*y5Tq0qlSbw8XUm6x1sXqMQ.png)
Finally let’s look at a few functions to provide human-readable strings from time_t
variables or tm
structs.
最后,让我们看一些从time_t
变量或tm
结构提供人类可读字符串的函数。
![Image for post](https://miro.medium.com/max/9999/1*XqMdnmbRM46acntRJRmeTA.png)
该项目 (The Project)
For this project I will write three functions to illustrate the types and functions listed above.
对于这个项目,我将编写三个函数来说明上面列出的类型和函数。
Get the current time as a
time_t
, use it to createtm
structs in both GMT and local time, then print out the members of the local time struct以
time_t
获取当前时间,使用它在GMT和本地时间中创建tm
结构,然后打印出本地时间结构的成员Create and initialize a
tm
struct, then usemktime
to both normalize thetm
and get atime_t
创建并初始化
tm
结构,然后使用mktime
标准化tm
并获取time_t
Get the local time and print it in various formats using
strftime
获取本地时间并使用
strftime
以各种格式打印
The project consists of just one file called datetime.c which you can clone/download the Github repository.
该项目仅包含一个名为datetime.c的文件,您可以克隆/下载Github存储库 。
This is the first part.
这是第一部分。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void current_time(void);
void create_time(void);
void time_to_string(void);
int main(int argc, char* argv[])
{
puts("-------------------");
puts("| codedrome.com |");
puts("| Dates and Times |");
puts("-------------------\n");
current_time();
// create_time();
// time_to_string();
return EXIT_SUCCESS;
}
void current_time(void)
{
// Get current time as time_t which
// is an integer, usually long.
// This is generally the number of
// seconds from midnight on 1 Jan 1970.
time_t t = time(NULL);
// Get tm structs from time_t.
// tm has members for seconds, minutes,
// hours, day, month, year etc.
struct tm* tm_gmt = gmtime(&t);
struct tm* tm_local = localtime(&t);
printf("Current GMT time is:\n%s\n", asctime(tm_gmt));
printf("Current local time is:\n%s\n", asctime(tm_local));
// Print the members of the local tm struct.
// Note these are all of type int.
puts("The members of the local tm struct are:");
printf("tm_sec %d\n", tm_local->tm_sec);
printf("tm_min %d\n", tm_local->tm_min);
printf("tm_hour %d\n", tm_local->tm_hour);
printf("tm_mday %d\n", tm_local->tm_mday);
printf("tm_mon %d\t0-based\n", tm_local->tm_mon);
printf("tm_year %d\tfrom 1900\n", tm_local->tm_year);
printf("tm_wday %d\t0-based from Sunday\n", tm_local->tm_wday);
printf("tm_yday %d\t0-based\n", tm_local->tm_yday);
printf("tm_isdst %d\t-1 = not known, 0 = no, 1 = yes\n", tm_local->tm_isdst);
}
The main
function merely calls the other three functions.
main
函数仅调用其他三个函数。
I don’t usually include a lot of comments unless something unusual is going on which needs an explanation, but as this code is intended mainly as a reference I have included comprehensive descriptions. Therefore I won’t include details of the code in the text.
除非正在进行一些不寻常的事情,需要解释,否则我通常不会包含很多评论,但是由于此代码主要是作为参考,因此我已经进行了全面的描述。 因此,我不会在文本中包含代码的详细信息。
When you have read the code and comments compile the program and run it:
阅读代码和注释后,编译程序并运行它:
gcc datetime.c -std=c11 -lm -o datetime ./datetime
gcc datetime.c -std=c11 -lm -o datetime ./datetime
![Image for post](https://miro.medium.com/max/9999/1*J_dzbAFs_ysmZk4QNeMS3A.png)
Note that tm_mon
, tm_wday
and tm_yday
are zero-based, and that the year counts up or down from 1900.
请注意, tm_mon
, tm_wday
和tm_yday
从零开始,并且年份从1900开始递增或递减。
Now let’s look at create_time
.
现在让我们看一下create_time
。
void create_time(void)
{
// Create and initialize a tm struct.
struct tm st = {.tm_sec = 30,
.tm_min = 15,
.tm_hour = 9,
.tm_mday = 12,
.tm_mon = 7 - 1, // 0-based so 6 is July
.tm_year = 2019 - 1900, // 1900 + or -
.tm_isdst = 1};
// Create a time_t from a tm struct.
// This also sets tm_wday and tm_yday.
time_t t = mktime(&st);
printf("The value of the time_t variable is:\n%ld\n\n", t);
printf("which represents:\n%s\n", ctime(&t));
puts("The mkdir function set these members of the tm struct:");
printf("tm_wday %d\t0-based from Sunday\n", st.tm_wday);
printf("tm_yday %d\t0-based\n", st.tm_yday);
}
When creating a tm
I have used 7 as the month but subtracted 1, and 2019 as the year but subtracted 1900. This emphasises that they start at 0 and 1900 respectively.
创建tm
我将7用作月份,但减去1,将2019用作年份,但减去1900。这强调了它们分别从0和1900开始。
After printing out the value of the time_t
variable both as a number and a human-readable string I have printed tm_wday
and tm_yday
to illustrate that the mktime
function sets these.
在将time_t
变量的值打印为数字和人类可读的字符串之后,我打印了tm_wday
和tm_yday
来说明mktime
函数设置了这些值。
The mktime
function also adjusts any values which exceed their maximum. For example if you create a tm
struct with a date of 31 June then mktime
will change it to 1 July. For this reason it is important to set all six date/time members even if you aren’t interested in them. If you do not they will contain garbage values which mktime
will use to adjust the members which you did set. (You don’t have to look far to find complaints about this “bug”!)
mktime
函数还可以调整任何超出其最大值的值。 例如,如果您创建日期为6月31日的tm
结构,则mktime
会将其更改为7月1日。 因此,即使您对六个日期/时间成员都不感兴趣,也很重要。 如果不这样做,它们将包含垃圾值, mktime
将使用这些值来调整您设置的成员。 (您不必费劲就可以找到有关此“错误”的投诉!)
In main comment out current_time();
, uncomment create_time();
and build and run again. This is the output.
在主要评论中, current_time();
,取消注释create_time();
然后重新构建并运行。 这是输出。
![Image for post](https://miro.medium.com/max/9999/1*mWLE0hnLQyXHMXqh4hOAWg.png)
The fixed string format provided by asctime
and ctime
is OK for demonstration or perhaps writing to a log but isn’t very flexible. The strftime
function allows us to specify a format string so we can create a string with the various members of a tm struct in any order or format we want.
由asctime
和ctime
提供的固定字符串格式可以演示或写入日志,但不是很灵活。 strftime
函数允许我们指定格式字符串,这样我们就可以使用所需的任何顺序或格式,使用tm结构的各个成员创建字符串。
strftime
takes the following arguments:
strftime
采用以下参数:
char* restrict n
— a buffer to hold the formatted datechar* restrict n
—一个缓冲区,用于保存格式化的日期size_t n
— the maximum number of characters to writesize_t n
—要写入的最大字符数const char* restrict format
— a string representing the formatconst char* restrict format
-表示格式的字符串const struct tm* restrict timeptr
— thetm
to create a string representation ofconst struct tm* restrict timeptr
—用于创建以下内容的字符串表示形式的tm
:
The format string can contain any number of specifiers consisting of the %
sign followed by an upper case or lower case letter. I won’t list all the valid letters but you might like to read this http://man7.org/linux/man-pages/man3/strftime.3.html.
格式字符串可以包含任意数量的说明符,由%
符号,大写或小写字母组成。 我不会列出所有有效字母,但是您可能想阅读http://man7.org/linux/man-pages/man3/strftime.3.html 。
Now take a look at the code which uses strftime
on the current time with three different formats.
现在来看一下在当前时间使用strftime
的三种不同格式的代码。
void time_to_string(void)
{
char datestring[64];
time_t t = time(NULL);
struct tm* tm_local = localtime(&t);
// YYYY-MM-DD
strftime(datestring, 64, "%Y-%m-%d", tm_local); // can use the %F shorthand
puts(datestring);
// Day, day of month, month, year in full
strftime(datestring, 64, "%A %d %B %Y", tm_local);
puts(datestring);
// HH:MM:SS
strftime(datestring, 64, "%H:%M:%S", tm_local); // can use the %T shorthand
puts(datestring);
}
After getting a tm
with the local time I have used strftime
with three different format string examples. A few of the more common formats have single letter shortcuts, two of which I have mentioned in the comments.
在获取本地时间的tm
之后,我将strftime
与三个不同格式的字符串示例一起使用。 一些较常见的格式具有单字母快捷键,我在注释中提到了其中的两个。
In main
comment out create_time();
, uncomment time_to_string();
and build and run again. This is the output.
在main
注释中, create_time();
,取消注释time_to_string();
然后重新构建并运行。 这是输出。
![Image for post](https://miro.medium.com/max/9999/1*eQZAgbE76w0-TnaH5M1yGg.png)
As you can see strftime
provides as much flexibility as you need. Not only do the various %
+ letter specifiers let you format the members of a tm
in any way you need but you can also include other characters or text in the output.
如您所见, strftime
提供了所需的灵活性。 各种%
+字母说明符不仅可以让您以所需的任何方式格式化tm
的成员,而且还可以在输出中包括其他字符或文本。
翻译自: https://medium.com/programming-in-c/dates-and-times-in-c-9fc7be4e3625
c语言中日期和时间