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

xxe27gdn  于 2022-12-03  发布在  其他
关注(0)|答案(3)|浏览(139)

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

struct tm mytime;
memset(&mytime, 0, sizeof(mytime));

因为 * 不是所有 * struct tm的字段从0都有效。A closer look on 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

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

nvbavucw

nvbavucw1#

如果假设以下两个规则,这是有意义的:

  • 从1开始存储值,如果这样可以最轻松地显示,而不必在常用日期格式中加减1
  • 在所有其他情况下(或者第一个规则可能会根据格式选择任一种方式时),从0开始存储值

应用规则:

  • tm_sectm_mintm_hour从0开始显示,因此从0开始存储。在12小时格式中,第一个小时为12,但其余小时可以从0开始“按原样”显示。
  • tm_mday从1开始显示,因此从1开始存储
  • tm_mon在日期(如24/02/1964)中从1开始显示,但对于日期(如24 th February 1964),从0开始存储以便于在数组中索引字符串也是有意义的,因此可以选择任一方式-〉从0开始
  • tm_year 20世纪年份可以按2年格式显示,例如24/02/64,否则添加1900,从1开始的情况没有意义
  • tm_wday通常通过索引字符串数组显示,从0开始
  • tm_yday没有明确的理由从1开始以便于显示,从0开始

因此,tm_mday是唯一一种从1开始存储以便于在所有常见情况下显示的情况。
来自C-89标准的asctime的参考实现与此一致,对任何值的唯一调整是将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;
     }
y4ekin9u

y4ekin9u2#

我猜巴比伦人决定用数字1来表示一个月的第一天(原因很明显),因为他们还没有发明数字0
(Same第1年为第一年的原因AC)
从那时起,没有人改变过月份的编号。

bkkx9g8r

bkkx9g8r3#

另一个可能的原因是,tm_mday == 0检查可以用来将这样的日期视为“null date”(或“not set”/“not available”),保留通过零初始化语义隐式初始化它的能力,如果为此目的使用了某个非零(比如INT_MIN)值,则这是不可能的。

相关问题