计算一年中星期三的发生次数

时间:2014-03-12 22:35:09

标签: c algorithm date std

我如何(快速)计算当年发生的星期三数?例如,函数num_wednesdays()将在2014年1月1日调用1,1月7日调用1,2014年1月8日调用2

修改 这就是我所确定的。

int num_wednesdays() {
  time_t now, then;
  struct tm * tmp;
  int today;
  time(&now);

  tmp = localtime(&now);
  today = tmp->tm_yday;
  tmp->tm_mon = 0;  
  tmp->tm_mday = 0;

  do {
    tmp->tm_mday++;
    then = mktime(tmp);
    tmp = localtime(&then);
  } while(tmp->tm_wday != 3);

  if(today < tmp->tm_yday)
    return 0;
  else
    return (today - tmp->tm_yday) / 7 + 1;
}

2 个答案:

答案 0 :(得分:2)

最简单的方法:由于星期三每7天发生一次,你只需要找到一年中第一个星期三的时间,然后计算自那天起的7天时段的数量。

答案 1 :(得分:0)

问题可以通过一些模运算和单localtime()调用以及不调用mktime()来解决。下面的函数num_weekday()将告诉您在给定参考时间到参考时间的那一年中,每周任何给定日期中有多少天发生了。如果给定时间是一周中的同一天,则计为已经发生。

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

static const int debug = 1;

extern int num_weekday(time_t ref_time, int req_dow);

static int mod(int x, int n)
{
    int r = x % n;
    if (r == 0)
        r = n;
    return r;
}

int num_weekday(time_t ref_time, int req_dow)
{
    assert(req_dow >= 0 && req_dow <= 6);
    struct tm *info = localtime(&ref_time);
    int wday_0101 = 6 - (info->tm_yday + 6 - info->tm_wday) % 7;
    int num_dow = (info->tm_yday + mod(wday_0101 + 7 - req_dow, 7)) / 7;
    if (debug)
    {
        printf("%.4d-%.2d-%.2d: yday = %3d; wday = %d; wday 01-01 = %d; "
                "req dow = %d; num dow = %2d\n",
                info->tm_year + 1900, info->tm_mon + 1, info->tm_mday, info->tm_yday,
                info->tm_wday, wday_0101, req_dow, num_dow);
    }
    return num_dow;
}

static void test_time(time_t ref_time, int req_dow)
{
    int num_days = num_weekday(ref_time, req_dow);
    if (!debug)
    {
        struct tm *info = localtime(&ref_time);
        printf("%.4d-%.2d-%.2d: yday = %3d; wday = %d; "
                "req dow = %d; num dow = %2d\n",
                info->tm_year + 1900, info->tm_mon + 1, info->tm_mday,
                info->tm_yday, info->tm_wday, req_dow, num_days);
    }
}

enum { SECS_PER_DAY  = 24 * 60 * 60         };
enum { SECS_PER_YEAR = 365 * SECS_PER_DAY   };
enum { YEAR_MIN = -6,  YEAR_MAX = -YEAR_MIN };
enum { DAY_MIN  = -15, DAY_MAX  = -DAY_MIN  };

int main(void)
{
    const time_t base = 1388600000;   // 1388600000 = 2014-01-01 18:13:20 +00:00
    for (int req_dow = 0; req_dow <= 6; req_dow++)
    {
        for (int year = YEAR_MIN; year <= YEAR_MAX; year++)
        {
            time_t start = base + year * SECS_PER_YEAR;
            for (int day = DAY_MIN; day <= DAY_MAX; day++)
                test_time(start + day * SECS_PER_DAY, req_dow);
        }
    }

    for (int req_dow = 0; req_dow <= 6; req_dow++)
        test_time(time(0), req_dow);

    return 0;
}

测试代码生成大量数据,包括以下输出。在Mac OS X 10.9.2,GCC 4.8.2,64位编译上测试。

…
2013-12-28: yday = 361; wday = 6; wday 01-01 = 2; req dow = 3; num dow = 52
2013-12-29: yday = 362; wday = 0; wday 01-01 = 2; req dow = 3; num dow = 52
2013-12-30: yday = 363; wday = 1; wday 01-01 = 2; req dow = 3; num dow = 52
2013-12-31: yday = 364; wday = 2; wday 01-01 = 2; req dow = 3; num dow = 52
2014-01-01: yday =   0; wday = 3; wday 01-01 = 3; req dow = 3; num dow =  1
2014-01-02: yday =   1; wday = 4; wday 01-01 = 3; req dow = 3; num dow =  1
2014-01-03: yday =   2; wday = 5; wday 01-01 = 3; req dow = 3; num dow =  1
2014-01-04: yday =   3; wday = 6; wday 01-01 = 3; req dow = 3; num dow =  1
2014-01-05: yday =   4; wday = 0; wday 01-01 = 3; req dow = 3; num dow =  1
2014-01-06: yday =   5; wday = 1; wday 01-01 = 3; req dow = 3; num dow =  1
2014-01-07: yday =   6; wday = 2; wday 01-01 = 3; req dow = 3; num dow =  1
2014-01-08: yday =   7; wday = 3; wday 01-01 = 3; req dow = 3; num dow =  2
2014-01-09: yday =   8; wday = 4; wday 01-01 = 3; req dow = 3; num dow =  2
2014-01-10: yday =   9; wday = 5; wday 01-01 = 3; req dow = 3; num dow =  2
2014-01-11: yday =  10; wday = 6; wday 01-01 = 3; req dow = 3; num dow =  2
2014-01-12: yday =  11; wday = 0; wday 01-01 = 3; req dow = 3; num dow =  2
2014-01-13: yday =  12; wday = 1; wday 01-01 = 3; req dow = 3; num dow =  2
2014-01-14: yday =  13; wday = 2; wday 01-01 = 3; req dow = 3; num dow =  2
2014-01-15: yday =  14; wday = 3; wday 01-01 = 3; req dow = 3; num dow =  3
2014-01-16: yday =  15; wday = 4; wday 01-01 = 3; req dow = 3; num dow =  3
2014-12-17: yday = 350; wday = 3; wday 01-01 = 3; req dow = 3; num dow = 51
2014-12-18: yday = 351; wday = 4; wday 01-01 = 3; req dow = 3; num dow = 51
2014-12-19: yday = 352; wday = 5; wday 01-01 = 3; req dow = 3; num dow = 51
2014-12-20: yday = 353; wday = 6; wday 01-01 = 3; req dow = 3; num dow = 51
2014-12-21: yday = 354; wday = 0; wday 01-01 = 3; req dow = 3; num dow = 51
2014-12-22: yday = 355; wday = 1; wday 01-01 = 3; req dow = 3; num dow = 51
2014-12-23: yday = 356; wday = 2; wday 01-01 = 3; req dow = 3; num dow = 51
2014-12-24: yday = 357; wday = 3; wday 01-01 = 3; req dow = 3; num dow = 52
2014-12-25: yday = 358; wday = 4; wday 01-01 = 3; req dow = 3; num dow = 52
2014-12-26: yday = 359; wday = 5; wday 01-01 = 3; req dow = 3; num dow = 52
2014-12-27: yday = 360; wday = 6; wday 01-01 = 3; req dow = 3; num dow = 52
2014-12-28: yday = 361; wday = 0; wday 01-01 = 3; req dow = 3; num dow = 52
2014-12-29: yday = 362; wday = 1; wday 01-01 = 3; req dow = 3; num dow = 52
2014-12-30: yday = 363; wday = 2; wday 01-01 = 3; req dow = 3; num dow = 52
2014-12-31: yday = 364; wday = 3; wday 01-01 = 3; req dow = 3; num dow = 53
2015-01-01: yday =   0; wday = 4; wday 01-01 = 4; req dow = 3; num dow =  0
2015-01-02: yday =   1; wday = 5; wday 01-01 = 4; req dow = 3; num dow =  0
2015-01-03: yday =   2; wday = 6; wday 01-01 = 4; req dow = 3; num dow =  0
2015-01-04: yday =   3; wday = 0; wday 01-01 = 4; req dow = 3; num dow =  0
…
2014-03-15: yday =  73; wday = 6; wday 01-01 = 3; req dow = 0; num dow = 10
2014-03-15: yday =  73; wday = 6; wday 01-01 = 3; req dow = 1; num dow = 10
2014-03-15: yday =  73; wday = 6; wday 01-01 = 3; req dow = 2; num dow = 10
2014-03-15: yday =  73; wday = 6; wday 01-01 = 3; req dow = 3; num dow = 11
2014-03-15: yday =  73; wday = 6; wday 01-01 = 3; req dow = 4; num dow = 11
2014-03-15: yday =  73; wday = 6; wday 01-01 = 3; req dow = 5; num dow = 11
2014-03-15: yday =  73; wday = 6; wday 01-01 = 3; req dow = 6; num dow = 11

请注意,它正确地将2014-12-31标识为2014年的第53个星期三。