Linux下date命令详解及C/C++代码实现

Linux date 命令用于显示系统日期和时间。 date 命令可以用于设置系统的日期和时间。 默认情况下,date 命令显示配置 unix/linux 操作系统的时区中的日期。如果你是超级用户 (root) ,才可以更改日期和时间。

Linux date 命令语法

Linux date 命令显示和设置系统日期和时间。 此命令还允许用户以不同格式打印时间并计算未来和过去的日期。

date [选项]… [+格式]
date [选项] [MMDDhhmm[[CC]YY][.ss]]

在这里插入图片描述
格式 FORMAT 控制着输出格式. 仅当选项指定为全球时间时本格式才有效。 分别解释如下:

       %%     文本的 %

       %a     当前区域的星期几的简写 (Sun..Sat)

       %A     当前区域的星期几的全称 (不同长度) (Sunday..Saturday)

       %b     当前区域的月份的简写 (Jan..Dec)

       %B     当前区域的月份的全称(变长) (January..December)

       %c     当前区域的日期和时间 (Sat Nov 04 12:02:33 EST 1989)

       %d     (月份中的)几号(用两位表示) (01..31)

       %D     日期(按照 月/日期/年 格式显示) (mm/dd/yy)

       %e     (月份中的)几号(去零表示) ( 1..31)

       %h     同 %b

       %H     小时(24 小时制显示,用两位表示) (00..23)

       %I     小时(12 小时制显示,用两位表示) (01..12)

       %j     (一年中的)第几天(用三位表示) (001..366)

       %k     小时(24 小时制显示,去零显示) ( 0..23)

       %l     小时(12 小时制显示,去零表示) ( 1..12)

       %m     月份(用两位表示) (01..12)

       %M     分钟数(用两位表示) (00..59)

       %n     换行

       %p     当前时间是上午 AM 还是下午 PM

       %r     时间,12 小时制显示 (hh:mm:ss [A/P]M)

       %s     从 197011000秒到现在历经的秒数 (GNU扩充)

       %S     秒数(用两位表示)(00..60)

       %t     水平方向的 tab 制表符

       %T     时间,24 小时制显示(hh:mm:ss)

       %U     (一年中的)第几个星期,以星期天作为一周的开始(用两位表示) (00..53)

       %V     (一年中的)第几个星期,以星期一作为一周的开始(用两位表示) (01..52)

       %w     用数字表示星期几 (0..6); 0 代表星期天

       %W     (一年中的)第几个星期,以星期一作为一周的开始(用两位表示) (00..53)

       %x     按照 (mm/dd/yy) 格式显示当前日期

       %X     按照 (%H:%M:%S) 格式显示当前时间

       %y     年的后两位数字 (00..99)

       %Y     年(4 位表示) (1970...)

       %z     按照 RFC-822 中指定的数字时区显示(, -0500) (为非标准扩充)

       %Z     时区(例如, EDT (美国东部时区)), 如果不能决定是哪个时区则为空

       默认情况下,0 填充数据的空缺部分.  GNU 的 date 命令能分辨在 `%'和数字指示之间的以下修改.

              `-' (连接号) 不进行填充 `_' (下划线) 用空格进行填充

如何在 Linux 中使用 date 命令,要显示当前系统时间和日期,请输入 date 命令:

在这里插入图片描述

输出显示星期几、月份中的哪一天、月份、年份、当前时间和时区。 默认情况下,date 命令设置为操作系统的时区。

Linux 日期命令格式选项

要格式化 date 命令的输出,可以使用以 + 号开头的控制字符。 格式控件以 % 符号开头,并由它们的当前值代替。

在这里,%Y 字符替换为当前年份,%m 替换为月份,%d 替换为月份中的第几天:
在这里插入图片描述
以 mm-dd-yy 格式显示日期,打开终端并输入以下日期命令:
在这里插入图片描述
只需将日期显示为 mm/dd/yy 格式:在这里插入图片描述
只显示时间:

在这里插入图片描述
要显示语言环境的 12 小时时钟时间,请输入: 在这里插入图片描述
要以 HH:MM 格式显示时间:

在这里插入图片描述
如何将时间/日期格式保存到 shell 变量?在 shell 提示符下键入以下命令即可获取 MM-DD-YYYY 格式的当前日期。

#!/bin/bash
NOW=$(date +"%m-%d-%Y")
FILE="backup.$NOW.tar.gz"
echo "Backing up data to /opt/time.$NOW.tar.gz file, please wait..."

在这里插入图片描述

date -u 选项

显示或设置全球时间(格林威治时间)

在这里插入图片描述

CST:中国标准时间(China Standard Time),这个解释可能是针对RedHat Linux。

UTC:协调世界时,又称世界标准时间,简称UTC,从英文国际时间/法文协调时间”Universal Time/Temps Cordonné”而来。中国大陆、香港、澳门、台湾、蒙古国、新加坡、马来西亚、菲律宾、澳洲西部的时间与UTC的时差均为+8,也就是UTC+8。

GMT:格林尼治标准时间(旧译格林威治平均时间或格林威治标准时间;英语:Greenwich Mean Time,GMT)是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。

date -d选项

–date 或-d 选项:以日期格式显示给定的日期字符串。 但这不会影响系统的实际日期和时间值。而是使用以字符串形式给出的日期和时间。

显示过去的日期

在 Linux 中使用 --date 选项显示过去的日期。 date 命令接受诸如“tomorrow”、“Friday”、“last Friday”、“next Friday”、“next week”等值。 因此,使用以下字符串打印过去的日期:

在这里插入图片描述

显示未来日期

–date 选项还可以显示未来的日期。 与过去的日期一样,您可以输入字符串来打印即将到来的日期:

在这里插入图片描述

在 Linux 中设置或更改日期

要手动更改系统时钟,请使用 set 命令。 例如,要将日期和时间设置为 2021 年 12 月 13 日下午 5:30,请键入:

date --set=“2021213 05:30”

大多数 Linux 发行版都使用 ntp 或 systemd-timesyncd 服务同步系统时钟,因此手动设置时钟时要小心。

date命令代码实现

int main(int argc, char *argv[])
{
	const char *errstr;
	struct tm *tp;
	int ch, rflag;
	char *format, buf[1024], *outzone = NULL;
	const char *pformat = NULL;
	long long val;
	
	rflag = 0;
	while ((ch = getopt(argc, argv, "af:jr:uz:")) != -1)
		switch(ch) 
		{
			case 'a':
				slidetime = 1;
				break;
			case 'f':		/* 用 strptime 解析  */
				pformat = optarg;
				break;
			case 'j':		/* 不要设置 */
				jflag = 1;
				break;
			case 'r':		/* 用户指定的秒数 */
				rflag = 1;
				//tval = strtonum(optarg, LLONG_MIN, LLONG_MAX, &errstr);
				//if (errstr)
				//	errx(1, "seconds is %s: %s", errstr, optarg);			
				val = strtoll(optarg, &buf, 0);
				tval = (time_t)val;				
				break;
			case 'u':		/* 在 UTC 中做所有事情  */
				if (setenv("TZ", "UTC", 1) == -1)
					err(1, "cannot unsetenv TZ");
				break;
			case 'z':
				outzone = optarg;
				break;
			default:
				usage();
		}
	argc -= optind;
	argv += optind;

	if (!rflag && time(&tval) == -1)
		err(1, "time");
	/* 要格式化 date 命令的输出,您可以使用以 + 号开头的控制字符*/
	format = "%a %b %e %H:%M:%S %Z %Y";

	/* 允许任何顺序的操作数 */
	if (*argv && **argv == '+') 
	{
		format = *argv + 1;
		argv++;
		argc--;
	}

	if (*argv) 
	{
		setthetime(*argv, pformat);
		argv++;
		argc--;
	}

	if (*argv && **argv == '+') 
	{
		format = *argv + 1;
		argc--;
	}

	if (argc > 0)
		errx(1, "too many arguments");

	if (outzone)
		setenv("TZ", outzone, 1);

	tp = localtime(&tval);
	if (tp == NULL)
		errx(1, "conversion error");
	strftime(buf, sizeof(buf), format, tp);
	printf("%s\n", buf);
	return 0;
}

#define	ATOI2(ar)	((ar) += 2, ((ar)[-2] - '0') * 10 + ((ar)[-1] - '0'))
void setthetime(char *p, const char *pformat)
{
	struct tm *lt, tm;
	struct timeval tv;
	char *dot, *t;
	time_t now;
	int yearset = 0;



	lt = localtime(&tval);

	lt->tm_isdst = -1;			/* correct for DST */

	if (pformat) 
	{
		tm = *lt;
		if (strptime(p, pformat, &tm) == NULL) 
		{
			fprintf(stderr, "trouble %s %s\n", p, pformat);
			badformat();
		}
		lt = &tm;
	} 
	else 
	{
		for (t = p, dot = NULL; *t; ++t) 
		{
			if (isdigit((unsigned char)*t))
				continue;
			if (*t == '.' && dot == NULL) 
			{
				dot = t;
				continue;
			}
			badformat();
		}

		if (dot != NULL) 
		{			/* .SS */
			*dot++ = '\0';
			if (strlen(dot) != 2)
				badformat();
			lt->tm_sec = ATOI2(dot);
			if (lt->tm_sec > 61)
				badformat();
		}
		else
			lt->tm_sec = 0;

		switch (strlen(p)) 
		{
			case 12:				/* cc */
				lt->tm_year = (ATOI2(p) * 100) - 1900;
				yearset = 1;
			case 10:				/* yy */
				if (!yearset) {
					/* mask out current year, leaving only century */
					lt->tm_year = ((lt->tm_year / 100) * 100);
				}
				lt->tm_year += ATOI2(p);
			case 8:					/* mm */
				lt->tm_mon = ATOI2(p);
				if ((lt->tm_mon > 12) || !lt->tm_mon)
					badformat();
				--lt->tm_mon;			/* time struct is 0 - 11 */
			case 6:					/* dd */
				lt->tm_mday = ATOI2(p);
				if ((lt->tm_mday > 31) || !lt->tm_mday)
					badformat();
			case 4:					/* HH */
				lt->tm_hour = ATOI2(p);
				if (lt->tm_hour > 23)
					badformat();
			case 2:					/* MM */
				lt->tm_min = ATOI2(p);
				if (lt->tm_min > 59)
					badformat();
				break;
			default:
				badformat();
		}
	}

	/* 将故障时间转换为 UTC 时钟时间  */
	if (pformat != NULL && strstr(pformat, "%s") != NULL)
		tval = timegm(lt);
	else
		tval = mktime(lt);
	if (tval == -1)
		errx(1, "specified date is outside allowed range");

	if (jflag)
		return;

	/* 设置时间  */
	if (slidetime) 
	{
		if ((now = time(NULL)) == -1)
			err(1, "time");
		tv.tv_sec = tval - now;
		tv.tv_usec = 0;
		if (adjtime(&tv, NULL) == -1)
			err(1, "adjtime");
	} 
	else 
	{

		tv.tv_sec = tval;
		tv.tv_usec = 0;
		if (settimeofday(&tv, NULL))
			err(1, "settimeofday");

	}

	if ((p = getlogin()) == NULL)
		p = "???";
	syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
}

在这里插入图片描述

总结

本篇讲解如何在 Linux 和类 Unix 系统上格式化日期。 有关更多信息,请使用 man 命令查看。

欢迎关注微信公众号【程序猿编码】,需要date命令完整源码的添加本人微信号(c17865354792)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值