我想查找给定日期的周数,其中包含一周的变量起始日和变量锚定天数。
我需要计算一年中任何一天的一周,但我需要能够改变一周的定义。定义一周归结为两个因素:
选择一周是从周日到周六,还是从周一到周日。
选择每周锚定的日期。
一周的开始和结束都是不言自明的,它只是决定在一周,前一个星期日或下一个星期日计算哪个星期日(或者如果我们看的日期是星期日,则决定哪个星期日一周它属于)。主播日将决定年度展期。假设星期三在yr1
,但第二天(星期四)在yr2
:
yr1
,一周52
的一部分(如果一年有53个锚定日,则有时为53)。 yr2
年,第01
周。我使用struct tm *
来捕获我想要转换的日期和时间,所以我有很多数据可以使用我只是不知道要做什么操作才能正确计算。我知道函数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
进入这些变量的数据都是正确的,正确的日期和时间,时区等。
答案 0 :(得分:2)
具有可变开始日期和锚定日期的一年中的一周
这个问题相当直接:找到一年中某一年的“一年中的一周”及其“一年中的一周”。
第1步:找到DayOfTheWeek
(0-6)。 mktime()
将struct tm
tm_yday
并将其tm_wday
(0-365)和mktime()
(0-6)成员设置为其他字段。对于% 7
,本周从星期日开始。 调整,对于其他模型的值为0到6 ,当星期几开始时 - 此部分相当琐碎。确保.tm_mday -= DayOfTheWeek;
不适用于否定数字。
步骤2,将日期调整为以mktime()
步骤3,通过添加3将日期调整为周中周。技巧:周中一天始终与同一年的同一日历年。
第4步:致电.tm.tm_year
重置.tm_yday
和.tm_yday
成员。将mktime()
除以7以获得一年中的一周(并将第一周加1作为第1周,而不是0)。
两次调用#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)
输出
row_number()