c - 具有可变开始和锚定日期的一年中的一周
c - Week of year with variable start and anchor days
剧情简介:
我想查找给定日期的周数,该日期具有可变的起始日和可变的锚定日。
完整版:
我需要计算一年中任何给定的一天落在哪一周,但我需要能够更改定义一周的内容。定义一周归结为两个因素:
选择星期日到星期六还是星期一到星期日。
选择一周的哪一天锚定。
一周的开始和结束是不言自明的,它只是决定一周中的哪个星期日,前一个星期日或下一个星期日(或者如果我们正在查看的日期是星期日,则决定它属于哪一周)。锚定日将决定年轮转。假设星期三在 yr1
但第二天(星期四)在 yr2
:
- 情况 1:星期三定义星期,因此星期的以下部分也是年份
yr1
、星期 52
的一部分(如果年份有 53 个锚定日,则有时为 53 ).
- 情况 2:星期四定义周,因此周的前一部分也在
yr2
年,周 01
。
我正在使用 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
可以抛出周数 00-53,甚至可以选择星期日和星期一之间的星期几开始,但是无法更改锚定日周所以年轮转不能那样工作。
欢迎提出任何想法或建议,因为此问题不会自行消失!谢谢!
编辑:在 struct tm *
中捕获时间的代码是:
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
进入这些变量的数据都是正确的,正确的日期和时间、时区等。
Week of year with variable start and anchor days
这个问题相当直接:找到给定年月日的 "week-of-the-year" 及其 "week-of-the-year year"。
第 1 步:找到 DayOfTheWeek
(0-6)。 mktime()
将采用 struct tm
并根据其他字段设置其 tm_yday
(0-365) 和 tm_wday
(0-6) 成员。对于 mktime()
,一周从星期日开始。 调整 的值为 0 到 6 对于其他模型 星期几开始的时间 - 这部分相当 琐碎。确保 % 7
不适用于负数。
第 2 步,将日期调整为一周的开始 .tm_mday -= DayOfTheWeek;
第 3 步,通过添加 3 将日期调整为一周的周中。技巧:周中日始终与一年中的星期年在同一日历年中。
第 4 步:调用 mktime()
重置 .tm.tm_year
和 .tm_yday
成员。将 .tm_yday
除以 7 得到一年中的第几周(并加 1,因为第一周是第 1 周,而不是 0)。
调用 mktime()
两次可以很好地处理所有边缘情况,如下所示。
#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)
剧情简介:
我想查找给定日期的周数,该日期具有可变的起始日和可变的锚定日。
完整版:
我需要计算一年中任何给定的一天落在哪一周,但我需要能够更改定义一周的内容。定义一周归结为两个因素:
选择星期日到星期六还是星期一到星期日。
选择一周的哪一天锚定。
一周的开始和结束是不言自明的,它只是决定一周中的哪个星期日,前一个星期日或下一个星期日(或者如果我们正在查看的日期是星期日,则决定它属于哪一周)。锚定日将决定年轮转。假设星期三在 yr1
但第二天(星期四)在 yr2
:
- 情况 1:星期三定义星期,因此星期的以下部分也是年份
yr1
、星期52
的一部分(如果年份有 53 个锚定日,则有时为 53 ). - 情况 2:星期四定义周,因此周的前一部分也在
yr2
年,周01
。
我正在使用 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
可以抛出周数 00-53,甚至可以选择星期日和星期一之间的星期几开始,但是无法更改锚定日周所以年轮转不能那样工作。
欢迎提出任何想法或建议,因为此问题不会自行消失!谢谢!
编辑:在 struct tm *
中捕获时间的代码是:
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
进入这些变量的数据都是正确的,正确的日期和时间、时区等。
Week of year with variable start and anchor days
这个问题相当直接:找到给定年月日的 "week-of-the-year" 及其 "week-of-the-year year"。
第 1 步:找到 DayOfTheWeek
(0-6)。 mktime()
将采用 struct tm
并根据其他字段设置其 tm_yday
(0-365) 和 tm_wday
(0-6) 成员。对于 mktime()
,一周从星期日开始。 调整 的值为 0 到 6 对于其他模型 星期几开始的时间 - 这部分相当 琐碎。确保 % 7
不适用于负数。
第 2 步,将日期调整为一周的开始 .tm_mday -= DayOfTheWeek;
第 3 步,通过添加 3 将日期调整为一周的周中。技巧:周中日始终与一年中的星期年在同一日历年中。
第 4 步:调用 mktime()
重置 .tm.tm_year
和 .tm_yday
成员。将 .tm_yday
除以 7 得到一年中的第几周(并加 1,因为第一周是第 1 周,而不是 0)。
调用 mktime()
两次可以很好地处理所有边缘情况,如下所示。
#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)