Skip to content

Commit 22c7b3a

Browse files
kemzebSam Fisher
and
Sam Fisher
authored
Have time.js use UTC-related getters/setters (#30857)
Before this patch, we were using `Date` getter/setter methods that worked with local time to get a list of Sundays that are in the range of some start date and end date. The problem with this was that the Sundays are in Unix epoch time and when we changed the "startDate" argument that was passed to make sure it is on a Sunday, this change would be reflected when we convert it to Unix epoch time. More specifically, I observed that we may get different Unix epochs depending on your timezone when the returned list should rather be timezone-agnostic. This led to issues in US timezones that caused the contributor, code frequency, and recent commit charts to not show any chart data. This fix resolves this by using getter/setter methods that work with UTC since it isn't dependent on timezones. Fixes #30851. --------- Co-authored-by: Sam Fisher <[email protected]>
1 parent 982b20d commit 22c7b3a

File tree

4 files changed

+22
-17
lines changed

4 files changed

+22
-17
lines changed

web_src/js/components/RepoCodeFrequency.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export default {
6767
const weekValues = Object.values(this.data);
6868
const start = weekValues[0].week;
6969
const end = firstStartDateAfterDate(new Date());
70-
const startDays = startDaysBetween(new Date(start), new Date(end));
70+
const startDays = startDaysBetween(start, end);
7171
this.data = fillEmptyStartDaysWithZeroes(startDays, this.data);
7272
this.errorText = '';
7373
} else {

web_src/js/components/RepoContributors.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export default {
114114
const weekValues = Object.values(total.weeks);
115115
this.xAxisStart = weekValues[0].week;
116116
this.xAxisEnd = firstStartDateAfterDate(new Date());
117-
const startDays = startDaysBetween(new Date(this.xAxisStart), new Date(this.xAxisEnd));
117+
const startDays = startDaysBetween(this.xAxisStart, this.xAxisEnd);
118118
total.weeks = fillEmptyStartDaysWithZeroes(startDays, total.weeks);
119119
this.xAxisMin = this.xAxisStart;
120120
this.xAxisMax = this.xAxisEnd;

web_src/js/components/RepoRecentCommits.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export default {
6262
const data = await response.json();
6363
const start = Object.values(data)[0].week;
6464
const end = firstStartDateAfterDate(new Date());
65-
const startDays = startDaysBetween(new Date(start), new Date(end));
65+
const startDays = startDaysBetween(start, end);
6666
this.data = fillEmptyStartDaysWithZeroes(startDays, data).slice(-52);
6767
this.errorText = '';
6868
} else {

web_src/js/utils/time.js

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
11
import dayjs from 'dayjs';
2+
import utc from 'dayjs/plugin/utc.js';
23
import {getCurrentLocale} from '../utils.js';
34

4-
// Returns an array of millisecond-timestamps of start-of-week days (Sundays)
5+
dayjs.extend(utc);
6+
7+
/**
8+
* Returns an array of millisecond-timestamps of start-of-week days (Sundays)
9+
*
10+
* @param startConfig The start date. Can take any type that `Date` accepts.
11+
* @param endConfig The end date. Can take any type that `Date` accepts.
12+
*/
513
export function startDaysBetween(startDate, endDate) {
14+
const start = dayjs.utc(startDate);
15+
const end = dayjs.utc(endDate);
16+
17+
let current = start;
18+
619
// Ensure the start date is a Sunday
7-
while (startDate.getDay() !== 0) {
8-
startDate.setDate(startDate.getDate() + 1);
20+
while (current.day() !== 0) {
21+
current = current.add(1, 'day');
922
}
1023

11-
const start = dayjs(startDate);
12-
const end = dayjs(endDate);
1324
const startDays = [];
14-
15-
let current = start;
1625
while (current.isBefore(end)) {
1726
startDays.push(current.valueOf());
18-
// we are adding 7 * 24 hours instead of 1 week because we don't want
19-
// date library to use local time zone to calculate 1 week from now.
20-
// local time zone is problematic because of daylight saving time (dst)
21-
// used on some countries
22-
current = current.add(7 * 24, 'hour');
27+
current = current.add(1, 'week');
2328
}
2429

2530
return startDays;
@@ -29,10 +34,10 @@ export function firstStartDateAfterDate(inputDate) {
2934
if (!(inputDate instanceof Date)) {
3035
throw new Error('Invalid date');
3136
}
32-
const dayOfWeek = inputDate.getDay();
37+
const dayOfWeek = inputDate.getUTCDay();
3338
const daysUntilSunday = 7 - dayOfWeek;
3439
const resultDate = new Date(inputDate.getTime());
35-
resultDate.setDate(resultDate.getDate() + daysUntilSunday);
40+
resultDate.setUTCDate(resultDate.getUTCDate() + daysUntilSunday);
3641
return resultDate.valueOf();
3742
}
3843

0 commit comments

Comments
 (0)