【问题标题】:Calculating the time until christmas day in c在c中计算直到圣诞节的时间
【发布时间】:2016-12-27 18:32:33
【问题描述】:

我正在尝试用 c 语言编写一个程序,告诉你距离圣诞节还有多少天。我以前从未使用过 time.h 库,所以我大部分时间都在使用它。我可以很容易地获得当前时间,但我的问题是我不确定如何正确输入圣诞节的信息,这会弄乱 差异时间计算。下面的代码每次运行时都会输出不同的数字,但无论我尝试什么,我都无法让它工作。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
time_t currentDate;
time (&currentDate);

struct tm * now;
now = localtime (&currentDate);

struct tm xmas;
xmas = *localtime(&currentDate);
xmas.tm_yday = 359;

double seconds = difftime(asctime(&xmas),asctime(&now));

double days=seconds/86400;

printf("%g days\n", days);


return 0;
}

【问题讨论】:

  • 你是说圣诞节是一年中的第 359 天?我敢肯定并非总是如此。如果是 12 月 30 日会发生什么?
  • time 函数不知道您在tm_yday 中输入了正确的值,并且它应该忽略其他元素。请参阅stackoverflow.com/a/9575245/2564301 了解正确的方法。
  • 由于asctime() 函数返回char *,因此该代码不应该在没有警告的情况下编译。此外,asctime() 返回一个指向静态数据的指针;当它被第二次调用时,之前的值被覆盖。这意味着您不知道将哪些值传递给difftime() — 尽管在某一层面上这并不重要,因为对difftime() 的调用无论如何都是不正确的。但是假设您确实需要这两个字符串;例如,您无法有效地写strcmp(asctime(&amp;xmas), asctime(&amp;now))

标签: c date time codeblocks countdown


【解决方案1】:

您在正确的轨道上,但 difftime 将 time_t 类型的变量作为参数。因此,不需要您使用的“现在”变量。您拥有的“xmas”变量应该以与初始化它的方式略有不同的方式进行初始化。然后你可以在其上使用 mktime() 将其转换为类型 time_t 以便在 difftime() 中使用。

请注意,您可以在此编码沙箱中免费在浏览器中运行/修改以下代码:https://www.next.tech/projects/4d440a51b6c4/share?ref=1290eccd

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    double seconds, days;
    time_t currentDate;
    struct tm *xmas, today;

    time (&currentDate);

    today = *localtime(&currentDate);

    xmas = localtime(&currentDate);
    xmas->tm_mon = 11; // 0 == January, 11 == December
    xmas->tm_mday = 25;
    if (today.tm_mday > 25 && today.tm_mon == 11)
        xmas->tm_year = today.tm_year + 1;

    seconds = difftime(mktime(xmas),currentDate);
    days = seconds/86400;

    printf("%g days\n", days);

    return 0;
}

参考 - http://www.cplusplus.com/reference/ctime/difftime/

【讨论】:

  • 你在正确的轨道上。但是,正如顶级 cmets 所述,如果今天的日期是(例如)12 月 26 日怎么办?
  • @CraigEstey 很棒的收获。我刚刚更新了它,如果已经过了 12 月 25 日,圣诞节的年份就会更新到下一年。
  • 感谢这帮助我解决了很多问题!不过有一件事,你为什么使用-&gt; 来表示xmas-&gt;tm_mon=11;xmas-&gt;tm_mday=25; 为什么xmas.tm_mon=11; 不一样?
  • @JM5042 我声明 xmas 是这一行的指针:struct tm *xmas, today;。因此,必须先解除对 xmas 的引用,然后才能访问其成员数据。说xmas-&gt;tm_mon=11; 相当于说(*xmas).tm_mon=11;。作为练习,您可以尝试在不使用 xmas 作为指针的情况下重写此代码。如果您需要任何其他说明,请告诉我,我很乐意为您提供帮助!
【解决方案2】:

首先,你应该阅读libc手册中关于日期和时间的章节:

https://www.gnu.org/software/libc/manual/html_node/Date-and-Time.html

C 中的日期和时间处理有点糟糕,所以你需要很好地理解这些概念,以免混淆。

主要任务是调用difftime,其中目标时间是圣诞节,开始时间是当前时间。由于 difftime 以 time_t 格式接收时间,因此我们需要 time_t 中的当前时间和圣诞节。对于 time_t 格式的当前时间,您可以使用 time() 函数。要将结构化日历时间转换为 time_t,您需要 mktime()。所以代码最终如下:

    #include <stdio.h>
    #include <time.h>

    int main(void)
    {
            time_t now;
            time_t christmas;
            struct tm tmp;
            double seconds;
            double days;

            time(&now);

            tmp.tm_sec = 0;
            tmp.tm_min = 0;
            tmp.tm_hour = 0;
            tmp.tm_mday = 25;
            tmp.tm_mon = 11; /* December == 11 */
            tmp.tm_year = 116; /* 2016 */
            tmp.tm_isdst = -1;

            christmas = mktime(&tmp);

            seconds = difftime(christmas, now);
            days = seconds/86400;

            printf("%g days untils christmas.\n", days);

            return 0;
    }

【讨论】:

    【解决方案3】:

    一些 MCU 根本没有浮点单元或只有 32 位 float,而使用 double 要么一开始就不可能,要么成本很高。

    这是一个仅整数版本,用于计算日期差(以天为单位)。

    #include <stdio.h>
    #include <stdlib.h>
    #include <limits.h>
    
    // format here is ISO-like: year, month, day; 1-based
    int daydiff(int y1, int m1, int d1, int y2, int m2, int d2, int *diff)
    {
      int days1, days2;
      const int mdays_sum[] =
          { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
    
      // no checks for the other bounds here, feel free to add them
      if (y1 < 1708 || y2 < 1708) {
        *diff = INT_MAX;
        return 0;
      }
      // we add the leap years later, so for now
      //   356 days 
      // + the days in the current month
      // + the days from the month(s) before
      days1 = y1 * 365 + d1 + mdays_sum[m1 - 1];
      // add the days from the leap years skipped above
      // (no leap year computation needed until it is March already)
      // TODO: if inline functions are supported, make one out of this mess
      days1 += (m1 <= 2) ?
          (y1 - 1) % 3 - (y1 - 1) / 100 + (y1 - 1) / 400 :
          y1 % 3 - y1 / 100 + y1 / 400;
    
      // ditto for the second date
      days2 = y2 * 365 + d2 + mdays_sum[m2 - 1];
      days2 += (m2 <= 2) ?
          (y2 - 1) % 3 - (y2 - 1) / 100 + (y2 - 1) / 400 :
          y2 % 3 - y2 / 100 + y2 / 400;
    
      // Keep the signed result. If the first date is later than the
      // second the result is negative. Might be useful.
      *diff = days2 - days1;
      return 1;
    }
    

    “离圣诞节还有几天?”这个问题的实际答案给了

    #include <time.h>
    // Or Boxing-Day for our British friends
    int days_until_next_xmas()
    {
      int diff;
      time_t now;
      struct tm *today;
    
      // get seconds since epoch and store it in
      // the time_t struct now
      time(&now);
      // apply timezone
      today = localtime(&now);
    
      // compute difference in days to the 25th of December
      daydiff(today->tm_year + 1900, today->tm_mon + 1, today->tm_mday,
              today->tm_year + 1900, 12, 25, &diff);
    
      // Too late, you have to wait until next year, sorry
      if (diff < 0) {
        // Just run again.
        // Alternatively compute leap year and add 365/366 days.
        // I think that running it again is definitely simpler.
        daydiff(today->tm_year + 1900, today->tm_mon + 1, today->tm_mday,
                today->tm_year + 1900 + 1, 12, 25, &diff);
      }
      return diff;
    }
    int main()
    {
      // days_until_next_xmas() returns INT_MAX in case of error
      // you might want to check
      printf("Next X-mas in %d days\n", days_until_next_xmas());
      exit(EXIT_SUCCESS);
    }
    

    上面的代码没有太多的边界检查。请添加它们,特别是如果 int 数据类型少于 32 位(虽然现在大多数 MCU 都是 32 位,但您可能不需要它并且仅为单个日期计算更改架构?)。如果是这种情况,请跳过将1900 添加到tm-&gt;tm_year 并更改1708 的检查。这将适用于 16 位 MCU。 承认 8 位 MCU 会变得更复杂一些。

    【讨论】:

      【解决方案4】:
      int days_before_christ_mass()
      {
          int months_day_size[] = {31,28,31,30,31,30,31,31,30,31,30,31};
      
      int christ_mass_day = 25;
      int months = 12;
      int day = 26;
      
      cout << "Month: " << months << endl;
      cout << "Day: " << day << endl;
      int zero_starter_month = months - 1;
      if (zero_starter_month < 11) {
          if (day <= months_day_size[zero_starter_month]) {
              int daysSummation = abs(day - months_day_size[zero_starter_month]);
              //cout << daysSummation << endl;
              for (int i = zero_starter_month + 1; i < 11; i++)
                  daysSummation += months_day_size[i];
      
              daysSummation = daysSummation + christ_mass_day;
              //cout << daysSummation << endl;;
              return daysSummation;
          }
          else {
              cout << "No such day" << endl;
              return -1;
          }
      }
      else if (zero_starter_month == 11) {
      
          if (day <= months_day_size[zero_starter_month]) {
              if (day <= christ_mass_day) {
                  return christ_mass_day - day;
              }
              else {
                  int day_summation = abs(day - months_day_size[zero_starter_month]);
                  for (int i = 0; i < 11; i++)
                      day_summation += months_day_size[i];
                  day_summation += christ_mass_day;
                  return day_summation;
              }
          }
          else {
              cout << "No such day" << endl
              return -1;
          }
      }
      else {
          cout << "There is no such month" << endl;
          return -1;
      }
      }
      

      此代码适用于正数 int 日和月输入,因为月和日永远不能为零和负数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-28
        • 1970-01-01
        • 2010-09-21
        相关资源
        最近更新 更多