c-一年中的星期,起始日期和锚定日期不定 [英] c - Week of year with variable start and anchor days

查看:100
本文介绍了c-一年中的星期,起始日期和锚定日期不定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想找到给定日期的周号,该周的开始日期和锚定日期都不同。

I want to find the week number of a given date with variable starting days and variable anchoring days for the week.

我需要计算一年中任何给定日期的一周,但是我需要能够更改定义一周的内容。定义一周归结为两个因素:

I need to calculate the week any given day lands on out of a year, but I need to be able to change what defines a week. Defining a week boils down to two factors:


  • 选择一周是从周日到周六还是从周一到周日。

  • Choosing whether the week goes from Sunday to Saturday or Monday to Sunday.

选择每周的主播日。

一周的开始和结束是不言自明的,它只需确定一周中哪个星期日,前一个星期日或下一个星期日(或者如果我们要查看的日期是星期日,则确定它属于哪个星期)即可。 )。锚定日将确定年度展期。假设星期三在 yr1 中,但是第二天(星期四)在 yr2 中:

The start and end of the week is self-explanatory, it simply will decide which Sunday to count in a week, the preceding Sunday or the following Sunday (or if the date we are looking at is a Sunday, decide to which week it belongs). The anchor day will determine year rollover. Assume Wednesday is in yr1 but the next day (Thursday) is in yr2:


  • 情况1:星期三定义了星期,因此,星期的以下部分也是年份 yr1 的一部分,星期 52 (如果该年份具有主播日的53,则有时为53)。

  • 情况2:星期四定义星期,因此也定义了星期几该周也在年份 yr2 中,在一周 01 中。

  • Case 1: Wednesday defines the week, and therefore the following portion of the week is also part of year yr1, week 52 (sometimes 53 if the year has 53 of the anchor day).
  • Case 2: Thursday defines the week, and therefore the previous portion of the week is also in year yr2, week 01.

我正在使用 struct tm * 捕获要转换的日期和时间,因此我有很多数据要使用,我根本不知道要进行什么操作才能正确计算出该值。我知道函数 strftime 可以抛出一个星期数00-53,甚至可以选择星期几在星期日和星期一之间开始,但是无法更改一周的主播日,因此年度结转不会

I am using a struct tm * to capture the date and time I want to convert, so I have lots of data to work with I simply don't know what manipulations to make in order to calculate this correctly. I know that the function strftime can toss out a week number 00-53 and can even pick which day the week starts on between Sunday and Monday, but there is no way to alter the anchor day of a week so year rollover doesn't work that way.

任何想法或建议都会受到赞赏,因为此问题不会自动消失!

Any ideas or suggestions are appreciated as this issue won't just go away on its own! Thanks!

编辑:在 struct tm * 中捕获时间的代码是:

The code to capture the time in a struct tm * is:

time_t time_stamp;
struct tm *time_local;

time(&time_stamp); // fills in the current time in seconds, GMT
time_local = localtime(&time_stamp); // translates seconds GMT to tm in local time zone

中将秒GMT转换为tm这些变量中的数据都是正确的,正确的日期以及时间,时区等。

The data coming in to these variables is all correct, the right date and time, timezone, etc.

推荐答案


一年中的一周中的开始日期和锚点日期可变

Week of year with variable start and anchor days

这个问题很直接:找到一年中的一周及其一年中的一周

This issue is fairly direct: find the "week-of-the-year" and its "week-of-the-year year" for a given year-month-day.

第1步:找到 DayOfTheWeek (0-6)。 mktime()将采用 struct tm 并设置其 tm_yday (0-365)和 tm_wday (0-6)成员基于其他字段。对于 mktime(),该周从星期日开始。 调整,值为0到6 (针对其他型号),该值是星期几开始的时间-这部分很简单。确保%7 不会应用于负数。

Step 1: Find the DayOfTheWeek (0-6). mktime() will take a struct tm and set its tm_yday (0-365) and tm_wday (0-6) members base on the other fields. For mktime(), the week starts on Sunday. Adjust with a value of 0 to 6 for other models of when the day-of-the-week begins - this part is fairly trivial. Insure % 7 is not applied to negative numbers.

步骤2,将日期调整为以<$开始的一周c $ c> .tm_mday-= DayOfTheWeek;

Step 2, Adjust the date to week's beginning with .tm_mday -= DayOfTheWeek;

第3步,通过添加3将日期调整为一周的中旬。技巧:工作日的中间日期始终与该年的同一周相同。

Step 3, Adjust the date to week's mid-week by adding 3. Trick: The mid-week day is always in the same calendar year as the week-of-the-year year.

第4步:致电 mktime()重置 .tm.tm_year .tm_yday 成员。将 .tm_yday 除以7得到一年中的一周(并加上1,因为第一周是第1周,而不是0)。

Step 4: Call mktime() to reset the .tm.tm_year and .tm_yday members. Divide .tm_yday by 7 to get the week-of- the year (and add 1 as the first week is week 1, not 0).

两次调用 mktime()可以很好地处理所有边缘情况,如下所示。

Calling mktime() twice well handles all edge cases as shown below.

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

// return 1 on failure, 0 on success
int tm_YearWeek(int y, int m, int d, int FirstDOW, int *year, int *week) {
  // Set to noon to avoid DST issues.
  struct tm tm = { .tm_year = y - 1900, .tm_mon = m - 1, .tm_mday = d, .tm_hour = 12};
  // Calculate tm_wday.
  if (mktime(&tm) == -1) {
    return 1;
  }
  // Find day-of-the-week: 0 to 6.
  // Week starts on Monday per ISO 8601
  // 0 <= DayOfTheWeek <= 6, (Monday, Tuesday ... Sunday)
  int DayOfTheWeek = (tm.tm_wday + (7 - 1) - FirstDOW%7) % 7;

  // Offset the month day to the 1st day of the week (Monday).
  // This may make tm.tm_mday <= 0 or > EndOfMonth
  tm.tm_mday -= DayOfTheWeek;
  // Offset the month day to the mid-week (Thursday)
  // tm.tm_mday  <= 0 or > EndOfMonth may be true
  tm.tm_mday += 3;
  // Re-evaluate tm_year and tm_yday  (local time)
  if (mktime(&tm) == -1) {
    return 1;
  }

  *year = tm.tm_year + 1900;
  // Convert yday to week of the year, stating with 1.
  //printf("doy %4d %4d\n", tm.tm_yday, tm.tm_yday/7 + 1);
  *week = tm.tm_yday / 7 + 1;
  return 0;
}

一些测试代码

#define FirstDOW_Monday 0
#define FirstDOW_Sunday 6
const char *FirstDOW_Ddd[7] =
    { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
void TestHarness_YearWeek(int y, int m, int d, int FirstDOW) {
  int ywd_year, ywd_week;
  int e = tm_YearWeek(y,m,d, FirstDOW, &ywd_year, &ywd_week);
  if (e) {
    fprintf(stderr, "Fail\n");
    exit(EXIT_FAILURE);
  }
  struct tm tm = { .tm_year = y - 1900, .tm_mon = m - 1, .tm_mday = d, .tm_hour = 12};
  mktime(&tm);
  printf("%s %4d-%2d-%2d --> Year/Week %04d-W%02d  (week starts: %s)\n",
      FirstDOW_Ddd[(tm.tm_wday + 6) % 7], y, m, d, ywd_year, ywd_week,
      FirstDOW_Ddd[FirstDOW]);
}

void TestHarness_2012(int year, int FirstDOW) {
  printf("            Jan %d\n", year);
  puts("    S   M   T   W   T   F   S");
  if (year == 2014)
    puts("                1   2   3   4");
  if (year == 2015)
    puts("                    1   2   3");
  for (int i = 28; i <= 31; i++)
    TestHarness_YearWeek(year-1, 12, i, FirstDOW);
  for (int i = 1; i <= 6; i++)
    TestHarness_YearWeek(year, 1, i, FirstDOW);
  puts("");
}

输出

            Jan 2014
    S   M   T   W   T   F   S
                1   2   3   4
Sat 2013-12-28 --> Year/Week 2013-W52  (week starts: Mon)
Sun 2013-12-29 --> Year/Week 2013-W52  (week starts: Mon)
Mon 2013-12-30 --> Year/Week 2014-W01  (week starts: Mon)1st 2014 week start:Dec 30,2013
Tue 2013-12-31 --> Year/Week 2014-W01  (week starts: Mon)
Wed 2014- 1- 1 --> Year/Week 2014-W01  (week starts: Mon)
Thu 2014- 1- 2 --> Year/Week 2014-W01  (week starts: Mon)
Fri 2014- 1- 3 --> Year/Week 2014-W01  (week starts: Mon)
Sat 2014- 1- 4 --> Year/Week 2014-W01  (week starts: Mon)
Sun 2014- 1- 5 --> Year/Week 2014-W01  (week starts: Mon)
Mon 2014- 1- 6 --> Year/Week 2014-W02  (week starts: Mon)

            Jan 2014
    S   M   T   W   T   F   S
                1   2   3   4
Sat 2013-12-28 --> Year/Week 2013-W52  (week starts: Sun)
Sun 2013-12-29 --> Year/Week 2014-W01  (week starts: Sun)1st 2014 week start:Dec 29,2013
Mon 2013-12-30 --> Year/Week 2014-W01  (week starts: Sun)
Tue 2013-12-31 --> Year/Week 2014-W01  (week starts: Sun)
Wed 2014- 1- 1 --> Year/Week 2014-W01  (week starts: Sun)
Thu 2014- 1- 2 --> Year/Week 2014-W01  (week starts: Sun)
Fri 2014- 1- 3 --> Year/Week 2014-W01  (week starts: Sun)
Sat 2014- 1- 4 --> Year/Week 2014-W01  (week starts: Sun)
Sun 2014- 1- 5 --> Year/Week 2014-W02  (week starts: Sun)
Mon 2014- 1- 6 --> Year/Week 2014-W02  (week starts: Sun)

            Jan 2015
    S   M   T   W   T   F   S
                    1   2   3
Sun 2014-12-28 --> Year/Week 2014-W52  (week starts: Mon)
Mon 2014-12-29 --> Year/Week 2015-W01  (week starts: Mon)1st 2015 week start:Dec 29,2014
Tue 2014-12-30 --> Year/Week 2015-W01  (week starts: Mon)
Wed 2014-12-31 --> Year/Week 2015-W01  (week starts: Mon)
Thu 2015- 1- 1 --> Year/Week 2015-W01  (week starts: Mon)
Fri 2015- 1- 2 --> Year/Week 2015-W01  (week starts: Mon)
Sat 2015- 1- 3 --> Year/Week 2015-W01  (week starts: Mon)
Sun 2015- 1- 4 --> Year/Week 2015-W01  (week starts: Mon)
Mon 2015- 1- 5 --> Year/Week 2015-W02  (week starts: Mon)
Tue 2015- 1- 6 --> Year/Week 2015-W02  (week starts: Mon)

            Jan 2015
    S   M   T   W   T   F   S
                    1   2   3
Sun 2014-12-28 --> Year/Week 2014-W53  (week starts: Sun)
Mon 2014-12-29 --> Year/Week 2014-W53  (week starts: Sun)
Tue 2014-12-30 --> Year/Week 2014-W53  (week starts: Sun)
Wed 2014-12-31 --> Year/Week 2014-W53  (week starts: Sun)
Thu 2015- 1- 1 --> Year/Week 2014-W53  (week starts: Sun)
Fri 2015- 1- 2 --> Year/Week 2014-W53  (week starts: Sun)
Sat 2015- 1- 3 --> Year/Week 2014-W53  (week starts: Sun)
Sun 2015- 1- 4 --> Year/Week 2015-W01  (week starts: Sun)1st 2015 week start:Jan 1, 2016
Mon 2015- 1- 5 --> Year/Week 2015-W01  (week starts: Sun)
Tue 2015- 1- 6 --> Year/Week 2015-W01  (week starts: Sun)

这篇关于c-一年中的星期,起始日期和锚定日期不定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆