是否有任何技术原因导致在编程中默认日期格式为YYYYMMDD而不是其他格式?


118

有什么工程上的原因为什么会这样?在RDBMS的情况下,我想知道它与性能有关,因为“ YEAR”比“ MONTH”更具体,例如:您只有2000年,而每年都有“ January”,这样可以更轻松,更快捷地按年份过滤/排序某些内容,这就是为什么年份第一的原因。

但是我不知道这真的有道理吗?有什么理由吗?


14
@IMil我们可能不喜欢它,但是经常将它们存储为字符串。
Honza Brabec

14
@candied_orange这很奇怪,尤其是在日期的情况下。
glglgl


19
附带说明一下,这种格式不是那种异类。例如,使用匈牙利语(可能还有其他一些语言)YYYY。MM。DD。是默认的书面日期格式,距计算机已经很长时间了。
Neinstein

31
在编程中,默认日期格式为“ YYYYMMDD”?如果那是真的,那会很好,但是,并非到处都是这样。RFC 822和RFC 850以及ANSI C asctime仍在许多地方广泛使用。RFC 3339和ISO 8601正在逐渐取代旧格式,这是很好的选择,它们肯定是将来应该使用的格式。更笼统地说,我想说的是ISO 8601基本格式(不带分隔符的普通YYYYMMDD)实际上不如 YYYY-MM-DD这样的其他格式常见。
Daniel Pryden

Answers:


386

这样,就可以使用默认的排序规则(即字典顺序排序)轻松地将日期排序为字符串。

这也是为什么使用两位数字指定月份和日期的原因(如果需要,请添加前导零)。

实际上,它是ISO 8601定义的日期格式之一。该标准还定义了日期和时间格式,2015-03-27T15:26:40Z也可以按字符串排序。

但是,YYYYMMDD的另一个好处是可以轻松地(不涉及子字符串或字符替换)将字符串解析为整数,并且仍然对整数使用默认顺序。


90
@lucaswxp:如果您为遵循特定模式的字符串编写特殊情况的比较,则当然可以根据需要将其设置为巴洛克式。这里的问题是,架构的设计使得词法顺序(以及词法数字感知顺序)也是逻辑顺序,因此不需要自定义。
Deduplicator18

19
@lucaswxp您的日期字符串可能不在内存中。实际示例:您已经有一个csv文件,该文件已按ISO日期和每年超过数百万的行进行了排序。并且您只想返回某些日期之间的行。您可以逐行(逐行)读取文件,直到到达第一个日期,然后将行加载到内存中,直到到达最后一个日期。您可以跳过文件的其余部分。但是,如果将日期另存为其他格式,或仅按年份排序,则在关闭文件之前,必须仔细阅读整个年度的记录。
Tom A. Vibeto

48
需要注意的是破折号是在ISO 8601可选的,因此YYYYMMDD ISO 8601
马丁巴

32
@Benoit已经提出了解决Y10K问题的建议。如果我们仍在使用相同的时代,则将转到AYYYYYMMDD,直到Y100K,这将是BYYYYYYMMDD,CYYYYYYYMMDD,DYYYYYYYYMMDD,EYYYYYYYYYMMDD。该前导的Alpha前缀可确保正确的排序顺序(前提是如果仍然使用任何YYYY ...日期,则“ A0YYYY ...”等都是无效的表示形式)。在某些年份中,当年位数可以被三整除时,每次更改字母前缀时,我们都会开始添加三位数,以确保在宇宙热死之前不会用完字母。
蒙蒂·哈德

35
重要的是要注意,使用这种格式,排序不仅“更轻松”。词法(基于字符)排序与时间排序等效,这意味着您可以在不进行解析的情况下对时间排序
jpmc26

135

尚未提及,但您很快就会忽略YYYY 内部的订单。那已经是几千年,几个世纪,几十年甚至几年了。也就是说,YYYY已经从最长周期到最短周期被命令。MM和DD也是如此,这就是数字系统的工作方式。

因此,要使字段之间的顺序字段的顺序一致,唯一的选择是YYYYMMDD。

正如zahbaz和Arseni Mourzenko指出的那样,YYYYMMDD格式很容易排序。这不是一个幸运的巧合,这是直接将最长持续时间的字段放在第一位的直接结果(并保持长度固定;我们在此引入了Y10K问题)。


34
当您在开玩笑时,此代码可能会严重困扰我们8000年。代码的寿命超出了所有人的预期……😓–
降低了

15
@deceze ISO8601已经提供了5位数字的年份,但是很有趣的是,看看当前哪些DateTime实现允许它。
扎克·弗拉格

4
@ZacFaragher,我敢肯定我们以后会有足够的时间来实现,而不必着急,对吧?
ilkkachu

51
@deceze为什么解冻我-您是否知道如何治愈癌症?不,那是9999年,您知道COBOL。
user3067860

6
您可能希望修正您的错字。这个词千年的复数千年,是强制性地用双-N在匹配双-N拼写拉美通谕为一年。当你只是一个单一的-N拼错了,现在不幸的单-N匹配肛门拉丁肛门与含义的外来词进入英语运动一样。简而言之,您总是需要用某种方式来拼写它,这意味着您正在谈论的是数千年,而不是数千个对接孔。:)
tchrist

57

有什么理由吗?

是。这些软件将使用ISO 8601

与其他日期格式相比,ISO 8601具有许多优点:

  • 这是带有规格文档的标准:)
  • 这是明确的。除非已超过13天,否则mm / dd / yyyy和dd / mm / yyyy可能会造成混淆。
  • 它按字典顺序按升序排序,因此不需要特殊的日期排序逻辑。这在文件名中尤其有用,在文件名中,按字典顺序排序的数字常常令人困惑(例如1_file, 10_file, 2_file)。
  • 它要求4位数字的年份和零填充的月份和年份。这避免了2000年问题和其他歧义。

至于为什么首先出现 ISO 8601的原因,是因为人们在国家/系统之间交换数据时发现日期格式不明确且令人困惑,因此他们需要明确的内容。

有关基本原理,请参见规范的介绍。

尽管自1971年以来就可以使用该领域的ISO建议和标准,但不同国家/地区已普遍使用不同形式的日期和时间数字表示形式。在跨国家边界互换此类表示的地方,可能会误解数字的含义,从而造成混乱和其他后果性的错误或损失。本国际标准的目的是消除误解的风险,避免混淆及其后果。

...

本国际标准保留了最常用的日期和时间,以及它们在早期国际标准中的表示形式,并为实践中使用的某些新表达式提供了独特的表示形式。它在信息交换中的应用,尤其是在数据处理系统和相关设备之间的交换,将消除因误解和由此产生的成本而产生的错误。推广此国际标准不仅将促进跨国际边界的互换,而且还将改善软件的可移植性,并将减轻组织内部以及组织之间的通信问题。

该标准将“基本”变体定义为最大程度地减少了定界符的使用。因此,YYYYMMDD是扩展格式的基本替代YYYY-MM-DD


4
我不知道ISO 8601除了YYYY-MM-DD之外还允许YYYYMMDD。
keuleJ

iso.org/iso-8601-date-and-time-format.html似乎表明YYYY-MM-DD的“扩展格式”是8601的唯一格式?
Oskar Austegard

3
@keuleJ在ISO 8601标准中,将诸如YYYYMMDD而不是YYYY-MM-DD之类的分隔符的使用最小化称为“基本”格式变体。
罗勒·布尔克

ISO 8601的另外两个好处:(a)易于通过机器进行解析,没有空格字符,没有本地化文本;(b)易于跨文化的人类理解,第一年就很容易识别(如果是当代的话),并且不假设英语。
罗勒·布尔克

55

这是因为其他所有实现方式都不明确。

2003/01/02是什么意思?2003年1月2日?还是在欧洲:2003年2月1日?如果您在年份中使用两位数字(如03年2月2日),情况将更加糟糕。

这就是为什么您使用YYYYMMDD的原因,这是使我们能够清晰地交流有关日期的约定,因为日期始终是20030201。(它使排序更容易)

(现在不要将其存储为整数2000万3万200和1.。好吗?好吗?)


14
“ 20030201作为日期总是很清楚”:绝对不是这样。除非您知道所使用的格式为YYYYMMDD(或者是YYYYDDMM或DDMMYYYY?...),否则它与“ 01/02/2003”一样含糊不清。您总是需要知道日期的格式;没有“约定”可以使事情变得明确。
Skomisa

6
@skomisa这是非常不正确的。ISO 8601专门出于您所述的原因定义了国际标准日期格式。其他格式都不是有效的日期格式,并且自19880605
K. Alan Bates

11
@ K.AlanBates您的日期不明确,除非我们假定应根据ISO 8601对其进行解析。–
Goyo

16
20030201是201AD年3月20日,对吧?
David Richerby

10
@Martijn,但特定于语言。在土耳其,它是Şubat而不是2月(在您认为您的代码有效之前,请始终检查Turkey)。
NH。

19

假设t1和t2是不同的整数,它们代表两次用YYYYMMDD格式写入。那么t1 <t2意味着t2在t1之后发生。

使用DD和MM优先格式会丢失此顺序。

IMO是唯一明智的格式。


1
除非您永远不会将其存储为整数,否则至少我从未见过或未考虑过它。
管道

5
@pipe:相信我,有人会的。我们维护着一个将YYYYMMDD存储为整数的旧系统。该设计可能起源于一些没有明确日期类型的旧数据库系统,并且为了向后兼容而保留该设计。不好看 不要这样
Heinzi

19
@pipe我在软件行业的经验是,每当有理智的人想说“但是你永远都不会做X”时,总是至少有一个反例
Joseph Rogers

5
@pipe在数据仓库中,通常使用yyyymmdd整数作为日期表的主键/代理键。
soapygopher

4
@ pipe,DNS区域的序列号是一个32位整数,在区域更改时必须增加。虽然它可能只是一个简单的数字,但常见的习惯用法是使用诸如2018092601之类的数字...然后,中描述了魔术数字的一些奇怪定义feature_test_macros(7),例如具有_POSIX_C_SOURCE > 200809L意味着支持POSIX.1-2008的功能...
ilkkachu

12

没有提到的一点是,在交互式输入中,这种格式允许控制输入。

系统无法在不知道特定年份和月份的情况下知道一个月是否有28、29、30或31天。当交互式输入命令以年份和月份为准时,它可以检查日期(最后插入)是否在允许的范围内。

当然,这个问题主要是关于日期格式的,但是可以说日期格式遵循呈现给用户的格式。


7

YYYYMMDD订单的日期与订购数字的日期相同:最重要的部分在前。MMDDYYYY就像将“一百二十三”写成“二十三十三”一样。

在我们的文化中,我们对MMDDYYYY具有天生的理解,因为作为人类,我们对时间有所了解,并且岁月缓慢。我们通常知道是哪一年。看到年份几乎无关紧要,因此我们将其推后一步。几个月的变化速度足以保持其重要性。其他文化则对此有所不同。世界上许多人更喜欢DDMMYYYY。


62
您可能需要改写“我们的文化”,因为在我的文化中是DDMMYYYY,所以它不是您自己的“我们的”文化
slebetman

66
使用MMDDYYYY日期格式的所有国家的综合地图img-9gag-fun.9cache.com/photo/a2mXmGd_700b.jpg
百富勤

9
似乎是一个奇怪的论点:“几个月变化的速度足以保持其重要性”->为什么不把日期放在第一位,因为变化速度甚至更快?
Wim Deblauwe

7
@JoelCoehoorn,很容易做到明确(“在我们的美国文化中”)。“我们的” /“我们”在这里通常用来表示“ stackexchange社区”。
AnoE

14
究竟。Stackoverflow是国际性的。您居住在美国并不表示,暗示或什至使其他人也更有可能。您不能对读者在这里的所在地做任何假设,因为他们遍布世界各地。而且,大多数读者既不是您,也不是OP,而是其他在Google上找到您答案的人。这则评论写在与您所生活的大陆不同的大陆上。虽然我们有自己的-嗯- 有趣的习惯,但我们肯定在这里不使用MM / DD / YYYY ...
cmaster

6

已经提到了排序,但是到目前为止,最有用的原因是将它们作为“字符串”进行比较,是的,以类似的方式对26个字符的时间戳进行排序。

我知道这样的比较对于排序至关重要,但是对于2元素排序通常很有用。

我曾在未采用此方法的项目中工作过,是的,程序员尝试(混合结果)将日期作为字符串进行比较。

漂亮的格式适用于客户端或排版。


5

此格式使字符串的字母顺序与日期的时间顺序相同。这很有用,因为许多工具提供按名称的字母顺序排序,例如,文件按名称排序,但没有办法从文件名中解析任意格式的日期并对其进行排序。


4

这是限制性的。想象一下YEAR,MONTH和DAY作为参数,格式为YYYYMMDD,每个参数比前一个更具限制性。

因此,如果您要搜索1970年发生的事情,可以通过搜索以开头的字符串来完成"1970*",但是如果您记住是哪个月份,则可以添加"197005*"。这样,日期的每个“参数”都会为您提供更具体的信息。

这是从不太具体的信息("1970*")转到更具体的信息("19700523")的唯一方法。


3
并不是一个很好的论据-搜索特定月份而不是特定年份发生的事情是很普遍的。
立方

1
如果1970*197005*表示“ glob”通配符语法,则可以通过搜索glob *1970或搜索一堆MMDDYYYY日期05*1970。您的答案可能隐含地假设了一些您没有明确提到的额外约束,并且可以通过解释您的假设来加以改善。
Quuxplusone

3
这是一种副作用,或者是描述其他答案提到的排序键顺序的另一种方式。但是,除非您将其限制为仅搜索前缀,否则此解释会分散。(更易于索引,但绝不是必需的)。
彼得·科德斯

这也意味着您可以使用相对简单的正则表达式选择日期序列...
Harper

1

为什么在编程中,默认日期格式为YYYYMMDD ...

这是一种人类可读的输入和输出格式,不一定以这种方式存储。

所有编程语言中,有超过三分之一是在以英语为主要语言的国家/地区开发的,而大多数现代语言都遵循某种描述标准-日期的国际标准是ISO 8601

更多信息:(TMI?)

随着时间的变化,通常向前,天数首先增加,然后是月数,最后是年数-如果我们有十进制日期(和十进制时间),可能会更容易理解-随着时间的流逝,数字会越来越大。对于人类来说,一目了然地查看数字并将其与另一个日期进行比较会更加容易。

计算机不在乎您要使用什么结构,在大多数(但不是全部)计算机中使用了二进制逻辑 -基数e实际上具有最低的基数经济性,但对于完整的序列而言并不是最有效也不最简单的。

日期的实际输入和输出格式因国家/地区异,并由本地化设置,而YYYYMMDD似乎最有意义,并且您习惯的用法在今天并不普遍,过去也不是。时间最长的一次,但即使在今天,罗马数字常用的日期

提前了解一年会告诉您一年中的天数,这是一年中可以经历的最大持续时间变化。它可以预先告诉您每个月要遵循的天数(用于在输入期间进行错误检查),如果下一年的输入与您的输入不一致,则允许第一天的输入可能需要备份您-可能使可访问的输入更加困难。关于日历格式,它也很重要。另请参阅极客日历及其十进制星标。

就计算机而言,它很可能使用UNIX Epoch time,即1970年1月1日星期四00:00:00协调世界时(UTC)以来经过的秒数。正好是86400秒 另见儒略日。YYYYMMDD格式只是以自我为中心的人类所偏爱的格式,除非另有说明,否则IAU将一年视为儒略年为365.25天(3155.576万秒)。


1
实际上,我见过的几乎每一个人类和软件都更喜欢其他格式。
Goyo

1
很高兴见到你!我是Dave,我更喜欢YYYYMMDD
逆向工程师

0

我见过的另一种用法是,您可以将日期存储为整数(即​​,存储在数据库中),每个日期仅使用4个字节。然后,使用YYYYMMDD意味着整数比较(通常是一条机器指令)的结果与所表示日期的比较结果相同。而且它的打印程度中等,易于阅读。在任何主流编程环境中,这些都不要求任何代码或特殊支持。

如果这些事情是您需要处理的大部分日期,并且您需要做很多事情,那么这种格式具有很大的吸引力。

相比之下,DD / MM / YYYY等常见格式的日期以10个字节作为ASCII字符字符串。YYYYMMDD字符串将其减少到8,并获得了“比较表示形式与比较日期具有相同的结果”的优点,但是即使这样,基于字符串的比较也是逐个字符而不是单个整数比较。


2
将日期打包成三个字节很简单。范围0000〜9999需要14位,01〜12需要4位,01〜31需要5位,总计23位。通过还使用三字节数量的剩余位,您可以表示32768年内的日期,并保持一天的分辨率。例如,可以使用它来表示日期范围为公元819年至公元24576年。通过将位打包为yyyyyyyyyyyymmmmddddd,十进制表示形式可以直接比较(尽管不是直接可读的,但是谁在乎数据库的物理存储?)。
CVn

0

月亮由绿色奶酪制成的原因相同:不是。在大多数情况下,默认格式是某种本地化的字符串。有时使用ISO格式,但通常使用破折号以提高可读性。YYYYMMDD(或%Y%m%dstrftime很少的话)很少是默认值。公平地说,我敢肯定我已经看过,但是现在我想不出一个例子。

Unix日期(GNU核心实用程序)

date

输出:

Wed Sep 26 22:20:57 CEST 2018

蟒蛇

import time
print(time.ctime())

输出:

Wed Sep 26 22:27:20 2018

C

#include <stdio.h>
#include <time.h>

int main () {
   time_t curtime;

   time(&curtime);
   printf(ctime(&curtime));
   return(0);
}

输出:

Wed Sep 26 22:40:01 2018

C ++

#include <ctime>
#include <iostream>

int main()
{
    std::time_t result = std::time(nullptr);
    std::cout << std::ctime(&result);
}

输出:

Wed Sep 26 22:51:22 2018

Java脚本

current_date = new Date ( );
current_date;

输出:

Wed Sep 26 2018 23:15:22 GMT+0200 (CEST)

SQLite的

SELECT date('now');

输出:

2018-09-26

LibreOffice Calc

在此处输入图片说明

字母数字

在此处输入图片说明

OnlyOffice

在此处输入图片说明

Python + numpy的

import numpy as np
pd.datetime64('now')

输出:

numpy.datetime64('2018-09-26T21:31:55')

Python +熊猫

import pandas as pd
pd.Timestamp('now', unit='s')

输出:

Timestamp('2018-09-26 21:47:01.277114153')

软件工程

在此处输入图片说明

apport.log

ERROR: apport (pid 9742) Fri Sep 28 17:39:44 2018: called for pid 1534, signal 6, core limit 0, dump mode 2

Alternatives.log

update-alternatives 2018-05-08 15:14:24: run with --quiet --install /usr/bin/awk awk /usr/bin/mawk 5 --slave /usr/share/man/man1/awk.1.gz awk.1.gz /usr/share/man/man1/mawk.1.gz --slave /usr/bin/nawk nawk /usr/bin/mawk --slave /usr/share/man/man1/nawk.1.gz nawk.1.gz /usr/share/man/man1/mawk.1.gz

cups / access.log

localhost - - [28/Sep/2018:16:41:58 +0200] "POST / HTTP/1.1" 200 360 Create-Printer-Subscriptions successful-ok

系统日志

Sep 28 16:41:46 pop-os rsyslogd:  [origin software="rsyslogd" swVersion="8.32.0" x-pid="946" x-info="http://www.rsyslog.com"] rsyslogd was HUPed

10
要添加到您的论点中,由于运行了脚本的计算机上的用户设置,其中有多少是用这种方式格式化的?
Topher Brink

第一个不是真正的“ bash”,它是日期程序(它Do 27. Sep 22:27:09 CEST 2018在这里输出。)
PaŭloEbermann

@PaŭloEbermann你是对的,我希望现在会更好。就像我说的那样,其中许多格式已本地化,因此您看到的实际格式将取决于您的本地化选项。
Goyo

3
尽管此答案的重点对面向最终用户的应用程序是正确的,但对于系统之间的数据交换,数据序列化,消息/数据协议,日志记录,跟踪,调试器等而言并非如此。ISO 8601标准正迅速成为针对系统管理员和程序员的此类使用的规范。与国际或地区无关的情况也一样。
罗勒·布尔克

@BasilBourque谢谢,我添加了在我自己的系统中发现的日志的随机样本。我没有其他类型的示例。但是我不认为面对特定领域默认使用ISO 8601的趋势,面对大量默认使用其他格式的软件,其基本变体使其成为“编程中的默认设置”。
Goyo

-1

迄今为止未提及的另一个好处是,所需的量化(将精确值分配为属于相同的通用值范围)是相对容易且快速的单个操作。

假设您正在编写一份报告,该报告总结了今天的事件,例如总销售额和销售数量。销售日期和时间存储为YYYYMMDDHHMISS,您只需要保留最左边的8个字符(如果是字符串)或整数除以1,000,000(即下限)即可将日期时间减少到销售日。

同样,如果您希望当月的销售额,则只保留最左边的6位数字,或除以100,000,000

当然,您可能会争辩说任何字符串操作都是可能的,可以将销售日期为“ 12-25-2018 12:34 pm”的日期时间进行子字符串化和多次操作,以获取月份和年份。以数字形式122520181234可以被分割和模化,相乘,除以更多,最终还产生一个月和一年的时间。但是该代码确实很难编写,阅读,维护和理解。

而且,如果日期格式为MM / DD / YYYY,但将其切成小块,则即使是复杂的数据库优化器也可能无法使用where子句的列索引。相比之下,存储YYYYMMDD表示并希望在2018年12月导致ilk的where子句dateasstring LIKE '201812%'dateasint BETWEEN 20181200 and 20181299-索引可以轻松用于

因此,如果没有用于日期的专用数据类型,则字符串/数字表示法是唯一的选择,以某种形式使用和存储时间,即从最长时间间隔到最短时间间隔right拥有许多好处,可简化理解,操纵,存储,检索和代码维护

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.