【问题标题】:How to check if date is valid using mktime in C?如何在 C 中使用 mktime 检查日期是否有效?
【发布时间】:2017-06-10 08:47:16
【问题描述】:

我的代码有点问题。我需要检查用户给定的日期是否有效。我想使用 2 个规则来检查它: 1. 日期是日历中的有效日期(例如 29.2.2015 无效,因为 2015 年 2 月只有 28 天) 2. 日和月最多只能是 2 个数字(例如第 10 天和第 02 天有效,但 010和 002 不是)。感谢所有帮助!

到目前为止,这是我的代码:

void dateValidator(const char *date1) {
struct tm date = {0};

int day1;
int month1;
int year1;

int vday;
int vmonth;
int vyear;

sscanf(date1, "%3d.%3d.%d",&day1,&month1,&year1);
/**How do I check that if sscanf reads more than 2 characters on month and day, date is 
invalid?**/

date.tm_year = year1 - 1900;
date.tm_mon = month1 - 1;
date.tm_mday = day1;
date.tm_isdst = -1;

vday = date.tm_mday;
vmonth = date.tm_mon;
vyear = date.tm_year;

mktime(&pvm);

if ((vday != date.tm_mday) || (vmonth != date.tm_mon) || (vyear != date.tm_year)) {
        /**This doesnt seem to work**/
        printf("Invalid date");
}
}

【问题讨论】:

  • mktime() 不验证范围。 10 月 40 日悄悄地转换为 11 月 9 日。
  • 好的,所以我需要单独检查闰日等?
  • 您可以使用mktime()“转换”并检查转换后的值是否等于原始值。
  • 但这就是我在那里所做的?我使用 mktime 进行转换,然后检查新值是否等于原始值 vday != date.tm_mday
  • 您在比较中使用了pvm 来调用mktime()date

标签: c date time scanf mktime


【解决方案1】:

我已经删除了我之前的答案并发布了另一个答案。实际上您的代码很好,您只需将正确的参数发送到mktime 并检查其返回值。 IE。改变:

mktime(&pvm);
if ((vday != date.tm_mday) || (vmonth != date.tm_mon) || (vyear != date.tm_year)) {
    /**This doesnt seem to work**/
    printf("Invalid date");
}

类似于:

r = mktime(&date);
if (r == -1 || (vday != date.tm_mday) || (vmonth != date.tm_mon) || (vyear != date.tm_year)) {
      printf("Invalid date");
}

并将变量r 声明为time_t r;

【讨论】:

  • 谢谢你,我如何检查其他规则(一个月和日期最多 2 个数字)?
  • 调整sscanf的第二个参数并查看返回值。
【解决方案2】:
int IsValidDate(int year, int month, int day)
{
    unsigned int leap;
    unsigned char mon_day[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

    /* check the rang of the year */
    if ((year < 1) || (year >= 3200))
    {
        return 0;
    }

    if ((month < 1) || (month > 12))
    {
        return 0;
    }

    /* if it's leep year */
    if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
    {
        leap = 1;
    }
    else
    {
        leap = 0;
    }

    mon_day[1] += leap;

    if ((day > mon_day[month - 1]) || (day < 1))
    {
        return 0;
    }

    return 1;
}

对于标尺 1,我写了这段代码来检查之前的日期。 我希望这段代码可以帮助到你。

标尺2很容易检查,可以通过格式化有效日期并与输入字符串进行比较来检查。

【讨论】:

  • 很好奇,为什么year &gt;= 3200
  • 顺便说一句,(year % 100 != 0)) || (year % 400 == 0)) 通常不适用于1582 之前的年份
  • @chux,没有理由year &gt;= 3200 ,你可以改变它。而且我不知道闰年规则是否适用于1582年之前的年份,您也可以更改它。
  • 注意:在 1582 年之前,使用了不同闰年规则,(year % 4 == 0)。闰年规则从 -46 年到 12 年开始,具体取决于古代文本的阅读方式。有时current leap year rule 应用到很早以前,即使它与人们当时实际使用的不一致。
  • @chux,谢谢,我会根据标尺更正我的代码。
【解决方案3】:

如果 sscanf 在月份和日期读取超过 2 个字符,如何检查日期是否无效?

日和月最多只能是 2 个数字 数字(例如,第 10 天和第 02 天有效,但 010 和 002 无效)。

一个简单的检查:在扫描结束时记录偏移量并测试1)它不是原始的0(扫描到那么远)和2)这是字符串的结尾,以便检测额外的data1[] 中的垃圾。将3d 更改为2d

int n = 0;
sscanf(date1, "%2d.%2d.%d %n",&day1,&month1,&year1, &n);
if (n > 0 && data1[n] == '\0') Success();
else Fail();

Pedantic 代码会检查 "%[]" 以禁止前导空格和 '+'

int n = 0;
sscanf(date1, "%*2[0-9].%*2[0-9].%*4[0-9] %n", &n);
if (n == 0 || data1[n]) Fail();
else {
  sscanf(date1, "%2d.%2d.%d",&day1,&month1,&year1);
  ...

如何使用 mktime 检查日期是否有效?

@Marian 发布了一个很好的解决方案,增加了对mktime() 的返回值的测试。

if (-1 == mktime(&data)) Fail();
if (vday != date.tm_mday) || (vmonth != date.tm_mon) || (vyear != date.tm_year) Fail();

【讨论】:

    猜你喜欢
    • 2012-03-15
    • 2012-04-16
    • 1970-01-01
    • 2017-02-28
    • 2020-01-24
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多