【问题标题】:Date comparison in CC中的日期比较
【发布时间】:2016-05-18 21:02:11
【问题描述】:

我有一些任务要编写一个比较两个日期并返回中间天数的 C 程序。

问题是,变量的标识符应该是 time.h 库中的一个,所以我不能对这两个日期使用字符串或整数。 我知道 time.h 中有变量的 time_t 标识符,但是我如何继续询问用户输入该类型的变量?我不知道应该为这种类型在 printf 或 scanf 中添加什么。另外,有什么方法可以检查用户输入是否有效?

为了比较这两者,我想我应该使用同样包含在 time.h 中的 difftime() 函数,但话又说回来,我不确定。我在某处读到它以秒为单位显示差异,不确定该来源是否合法,但我真的不需要。我需要几天,因为我正在处理日期。

网上没有太多关于这个的资料,这就是我寻求帮助的原因。提前致谢!

【问题讨论】:

  • 您可以选择任何您希望用户输入日期的格式,只要您可以将这些输入转换为您计划使用的time.h 函数理解的时间表示。无论如何,用户都不应该输入time_t 值,因为它们作为日期表示对用户来说是不直观的。顺便说一句,您只需阅读time.h 标头即可了解time_t 的基本类型是什么,以确定如果您仍然想走那条路,则使用scanf 格式。
  • 看起来大多数值都是ints,scanf(%d) 为:pubs.opengroup.org/onlinepubs/007908775/xsh/time.h.htmltime_t 不是指定类型,因此您必须找到适合您系统的类型:stackoverflow.com/questions/471248/…
  • 稍加注意,您可以使用mktime(),也许还可以使用strftime()——如果您有一个POSIX-ish系统,也许还可以使用strptime(),但是strptime()使用起来有点棘手(但是大多数与日期相关的事情都有点棘手)。

标签: c date comparison time.h


【解决方案1】:

我假设您只想要两个日期之间的天数(而不是时间)。如其中一个 cmets 所述,为用户输入选择您想要的任何格式,然后对其进行解析。

要求作为日期输入的最简单格式之一是 yyyymmdd 形式的整数。

因此,例如,如果我想查找从我今年的生日(2016 年 5 月 27 日)到独立日(7 月 4 日)的天数,我将输入程序 20160527 和 20160704。

作为整数,它们相对容易转换为月、日和年。

声明一个结构体 tm 并为每个设置月日和年:

// Lets say the above dates were read into integers indate1 and indate2,
// so indate1 = 20160527 and indate2 = 20160704

#include <time.h>

struct tm dt = {0};
dt.tm_year = (indate1/10000) - 1900;
dt.tm_mon  = (indate1/100)%100;
dt.tm_mday = (indate1%100);

// Now convert to time_t:
time_t dt1 = mktime(&dt);

// Now do the same for indate2:
dt.tm_year = (indate2/10000) - 1900;
dt.tm_mon  = (indate2/100)%100;
dt.tm_mday = (indate2%100);
time_t dt2 = mktime(&dt);

// Now take the difference between the two dates:
double seconds = difftime( dt2, dt1 );

// Now convert to number of days:
unsigned long days = ( seconds / (60*60*24) );
fprintf( stdout, "The number of days between those two dates is %ld\n", days);

【讨论】:

    【解决方案2】:

    time_t 类型只是秒计数器。您想将其转换为 struct tm* 调用 localtime(time_t*)char *ctime(time_t*) 会给你一个字符串表示。对于格式化的输入和输出,您必须自己与 struct tm 的各个成员合作。

    【讨论】:

      【解决方案3】:

      除了基于整数输入手动打包struct tm,您还可以使用strptime 直接处理string 输入。 strptime 将根据提供的format 字符串将作为其第一个参数提供的字符串转换为struct tm

      根据您处理的输入类型,您可能会发现这更方便。一个简短的例子是:

      #define _XOPEN_SOURCE
      
      #include <stdio.h>
      #include <stdlib.h>
      #include <time.h>
      
      int main (int argc, char **argv) {
      
          char *dtstr1 = argc > 1 ? argv[1] : "20160527";
          char *dtstr2 = argc > 2 ? argv[2] : "20160704";
          struct tm dt = {0};
          time_t dt1 = 0, dt2 = 0;
      
          /* convert input strings to struct tm */
          strptime (dtstr2, "%Y%m%d", &dt);    
          dt2 = mktime (&dt);
      
          strptime (dtstr1, "%Y%m%d", &dt);    
          dt1 = mktime (&dt);
      
          /* get difference in calendar time */
          double seconds = difftime (dt2, dt1);
      
          /* convert to number of days */
          long days = (seconds/(60*60*24));
      
          if (seconds < 0) /* output difference with occurrence orientation */
              printf ("%s occurs %ld days after %s\n", dtstr1, -days, dtstr2);
          else if (seconds > 0)
              printf ("%s occurs %ld days before %s\n", dtstr1, days, dtstr2);
          else
              printf ("%s and %s are contemporaneous\n", dtstr1, dtstr2);
      
          return 0;
      }
      

      注意:虽然不太可能,但您可以在 days 转换中检查溢出)

      使用/输出示例

      $ ./bin/time_diff_days
      20160527 occurs 38 days before 20160704
      
      $ ./bin/time_diff_days 20160101 20150101
      20160101 occurs 365 days after 20150101
      
      $ ./bin/time_diff_days 20150101 20150101
      20150101 and 20150101 are contemporaneous
      

      如果您有任何问题,请告诉我。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-15
        • 2012-01-20
        • 1970-01-01
        相关资源
        最近更新 更多