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

eck*_*kes 8 c time struct mktime

回答另一个问题时,我告诉OP他需要struct tm正确初始化他的变量,但需要小心,因为他不能简单地使用

struct tm mytime;
memset(&mytime, 0, sizeof(mytime));
Run Code Online (Sandbox Code Playgroud)

因为并非所有领域struct tm都有效0.在仔细一看struct tm给我看,正是一个领域struct tm不具有0作为有效值,即tm_mday:

int    tm_sec   seconds [0,61]
int    tm_min   minutes [0,59]
int    tm_hour  hour [0,23]
int    tm_mday  day of month [1,31]
int    tm_mon   month of year [0,11]
int    tm_year  years since 1900
int    tm_wday  day of week [0,6] (Sunday = 0)
int    tm_yday  day of year [0,365]
int    tm_isdst daylight savings flag
Run Code Online (Sandbox Code Playgroud)

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

sam*_*gak 5

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

  • 如果允许最简单的显示而不必以通用日期格式加或减一个,则存储从1开始的值
  • 在所有其他情况下(或第一条规则可以根据格式任意选择),请存储从0开始的值

应用规则:

  • tm_sectm_mintm_hour显示成存储从0开始在12小时格式的第一个小时为12从0开始,但其余的可以显示“原样”由从0开始。
  • tm_mday 从1开始显示,所以从1开始存储
  • tm_mon 从1开始显示在1964年2月24日之类的日期中,但是从0开始存储也很有意义,以便于在1964年2月24日这样的日期中为数组中的字符串编制索引,因此可以采用两种方式->从0开始
  • tm_year 20世纪的年份可以按2年格式显示,例如24/02/64,或者加1900,在任何情况下都不应该从1开始
  • tm_wday 通常通过索引从0开始的字符串数组来显示
  • tm_yday 为了清楚起见,没有明确的理由从1开始,从0开始

因此tm_mday,在所有常见情况下,从1开始存储它具有明显的优势,这是唯一明显的优点,以便于显示。

的参考实现asctimeC-89标准是与此一致,唯一的调整是任何值的至1900添加到tm_year

     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;
     }
Run Code Online (Sandbox Code Playgroud)

  • tm_mon的理由令人信服。您还可以将所有其他内容排列在一个数组中。并且“ tm_wday”和“ tm_yday”也不遵循“规则1”。 (2认同)

DrK*_*och 0

我猜巴比伦人决定1在一个月的第一天使用数字(出于非常明显的原因),因为他们0还没有发明数字。

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

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

  • @DrKoch 为了好玩:过度简化:第 10 个月是 12 月、11 月 9 日、10 月 8 日和 9 月 7 日,从 3 月开始今年,所有闰年垃圾都在 2 月的最后一个月。然后政客们也介入其中。朱利叶斯·凯撒解决了这个问题,并于第二年被暗杀。这就是修复日历所得到的结果。 (5认同)
  • 但为什么 `tm_mon` 从 0 开始而不是从 1 开始? (3认同)