Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么TMmday从1开始,而struct tm的所有其他元素从0开始?_C_Time_Struct_Mktime - Fatal编程技术网

为什么TMmday从1开始,而struct tm的所有其他元素从0开始?

为什么TMmday从1开始,而struct tm的所有其他元素从0开始?,c,time,struct,mktime,C,Time,Struct,Mktime,同时,我告诉OP他需要正确初始化他的struct tm变量,但需要小心,因为他不能简单地使用 struct tm mytime; memset(&mytime, 0, sizeof(mytime)); 因为并非所有的struct tm字段都在0中有效。向我显示,正是struct tm的字段没有0作为有效值,即tm\u mday: 为什么??对于这个元素,0应该是无效值???这个决定背后的想法是什么?我猜巴比伦人决定在一个月的第一天使用数字1,因为他们还没有发明数字0 (与第一年为第一年

同时,我告诉OP他需要正确初始化他的
struct tm
变量,但需要小心,因为他不能简单地使用

struct tm mytime;
memset(&mytime, 0, sizeof(mytime));
因为并非所有的
struct tm
字段都在
0
中有效。向我显示,正是
struct tm
字段没有
0
作为有效值,即
tm\u mday


为什么??对于这个元素,
0
应该是无效值???这个决定背后的想法是什么?

我猜巴比伦人决定在一个月的第一天使用数字
1
,因为他们还没有发明数字
0

(与第一年为第一年AC的原因相同)


从那时起,没有人改变月份的编号。

如果您假设以下两条规则,这是有道理的:

  • 存储从1开始的值,如果该值允许最简单的显示,而无需在常用日期格式中添加或减去一个值
  • 在所有其他情况下(或者当第一条规则可以根据格式进行任何选择时),存储从0开始的值
适用规则:

  • tm_秒
    tm_分钟
    tm_小时
    从0开始显示,因此从0开始存储。在12小时格式中,第一个小时为12小时,但其余时间可以从0开始“按原样”显示
  • tmmday
    从1开始显示,因此从1开始存储
  • tm_mon
    在日期(如1964年2月24日)中从1开始显示,但也可以从0开始存储,以便在数组中为日期(如1964年2月24日)的字符串编制索引,因此可以选择任何一种方式->从0开始
  • tm_year
    20世纪年份可以按2年格式显示,例如24/02/64,或者添加1900,从1开始的任何情况都没有意义
  • tm_wday
    通常通过索引字符串数组显示,从0开始
  • tm_yday
    没有明确的理由从1开始为便于显示,从0开始
因此,
tm_mday
是唯一一种从1开始存储以便于在所有常见情况下显示的明显优势

来自的
asctime
的参考实现与此一致,对任何值的唯一调整是将1900添加到
tm\u年

     char *asctime(const struct tm *timeptr)
     {
         static const char wday_name[7][3] = {
                  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
         };
         static const char mon_name[12][3] = {
                  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
         };
         static char result[26];

         sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
                  wday_name[timeptr->tm_wday],
                  mon_name[timeptr->tm_mon],
                  timeptr->tm_mday, timeptr->tm_hour,
                  timeptr->tm_min, timeptr->tm_sec,
                  1900 + timeptr->tm_year);
         return result;
     }

tm_year
也从1开始(没有年份“零”),它只是减少了1900,这可能掩盖了零的缺失通常,所有值的范围都最适合直接显示(小时..秒)或索引字符串数组(月)。@CiaPan:
索引字符串数组
听起来非常合理,
tm_yday
没有字符串索引,其中
0
是有效的。@CiaPan A
tm_year
为零很好:它表示年份
1900
。我不知道这是否是原理的一部分,但是如果
tm_mday
从1开始,要找到下一个/上一个星期天,你只需执行
tm_mday-tm_yday
(和±7)等,因此它允许相对“干净”公式。只是一些猜测。秒、分钟、小时、月、年有固定的转换,但天没有。例如,1m=60s;1h=60m;1month=???day;1y=12m。因此,您可以使用
mod
转换为s/m/h/y,例如
xmod 60s
,'xmod 60m',
xmod 12m
,这可能会产生
0
s,
0
m,
0
h结果。但我们不会将
mod
应用于day,例如
x mod???day
(基数为30?31?或29?)。但是为什么
tm_mon
从0开始,而不是从1开始?@MichaelWalz:请参见上面CiaPan的注释()。索引字符串数组可能是一种解释……第一个月被称为“一月”,而不是“0”或“1”,因此您无论如何都需要一个查找表。在C@eckes中,此表最自然地使用一个从0开始的整数进行索引。但是零对于
tm\u year
有效。如果
tm\u mday
1
开始,则因为它“不需要索引字符串数组”,那么为什么不从
1
开始呢?@DrKoch为了好玩:过于简单化:第10个月是12月,11月9日,10月8日和9月7日,从3月开始,所有闰年垃圾都是在最后一个月2月。然后政客们参与其中。朱利叶斯·凯撒解决了这个问题,是阿萨斯第二年的日历。这就是修日历的结果。
tm_-mon
的理由没有说服力;你也可以把所有其他东西放在一个数组中。
tm_-wday
tm_-yday
不遵循“规则1”或者。@BlueMoon没有明确的理由说明为什么tm_wday和tm_yday如果从1开始存储会更容易显示,因此规则1适用于IMO。@Scooter,一年中的某一天没有用在任何常见的日期显示格式中,因此其原理没有月的某一天那么有说服力,即.Hmmm
静态字符结果[26];sprintf(结果,“%.3s%.3s%3d%.2d:%.2d:%.2d%d\n”,
适合利用具有大值的字段进行攻击。相比字节成本,黑客关注度并没有那么高。我不觉得这很有说服力。大多数情况下,你会将月份显示为一个数字,例如
2018-03-19
19.3.2018
3/19/2018
;因此每次你都必须添加1。
     char *asctime(const struct tm *timeptr)
     {
         static const char wday_name[7][3] = {
                  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
         };
         static const char mon_name[12][3] = {
                  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
         };
         static char result[26];

         sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
                  wday_name[timeptr->tm_wday],
                  mon_name[timeptr->tm_mon],
                  timeptr->tm_mday, timeptr->tm_hour,
                  timeptr->tm_min, timeptr->tm_sec,
                  1900 + timeptr->tm_year);
         return result;
     }