c-一年中的星期,起始日期和锚定日期不定 [英] c - Week of year with variable start and anchor days
问题描述
我想找到给定日期的周号,该周的开始日期和锚定日期都不同。
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
, week52
(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
, week01
.
我正在使用 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屋!