fix(docs-infra): correctly display event dates on all timezones (#41053)

Previously, the event dates displayed on the angular.io "Events" page
(`/events`) was off by one day on timezones with a negative offset from
UTC. See
https://github.com/angular/angular/pull/41050#issuecomment-788958888.

This commit fixes it by using the `getUTC*` methods of the `Date` object
to extract the date info, which are not affected by the user's timezone.

PR Close #41053
This commit is contained in:
George Kalpakas 2021-03-02 18:57:26 +02:00 committed by Zach Arend
parent 5eab6e14f1
commit cb16035fd3
4 changed files with 104 additions and 76 deletions

View File

@ -161,6 +161,7 @@
"rimraf": "^2.6.1",
"semver": "^5.3.0",
"shelljs": "^0.8.4",
"timezone-mock": "^1.1.3",
"tree-kill": "^1.1.0",
"ts-node": "^8.4.1",
"tslint": "~6.1.0",

View File

@ -1,5 +1,6 @@
import { Injector } from '@angular/core';
import { Subject } from 'rxjs';
import * as tzMock from 'timezone-mock';
import { Duration, Event, EventsComponent } from './events.component';
import { EventsService } from './events.service';
@ -132,86 +133,107 @@ describe('EventsComponent', () => {
});
describe('getEventDates()', () => {
describe('(without workshops)', () => {
it('should correctly format the main event date', () => {
const testEvent = createMockEvent('Test', {start: '2020-06-20', end: '2020-06-20'});
expect(component.getEventDates(testEvent)).toBe('June 20, 2020');
});
// Test on different timezones to ensure that event dates are processed correctly regardless of
// the user's local time.
const timezones: tzMock.TimeZone[] = [
'Australia/Adelaide', // UTC+9.5/10.5
'Brazil/East', // UTC-3
'UTC', // UTC
];
it('should correctly format the main event date spanning mupliple days', () => {
const testEvent = createMockEvent('Test', {start: '2019-09-19', end: '2019-09-21'});
expect(component.getEventDates(testEvent)).toBe('September 19-21, 2019');
});
for (const tz of timezones) {
describe(`on timezone ${tz}`, () => {
// NOTE: `timezone-mock` does not work correctly if used together with Jasmine's mock clock.
beforeEach(() => tzMock.register(tz));
afterEach(() => tzMock.unregister());
it('should correctly format the main event date spanning mupliple months', () => {
const testEvent = createMockEvent('Test', {start: '2019-10-30', end: '2019-11-01'});
expect(component.getEventDates(testEvent)).toBe('October 30 - November 1, 2019');
});
});
describe('(without workshops)', () => {
it('should correctly format the main event date', () => {
const testEvent = createMockEvent('Test', {start: '2020-06-20', end: '2020-06-20'});
expect(component.getEventDates(testEvent)).toBe('June 20, 2020');
});
describe('(with workshops)', () => {
it('should correctly format event dates with workshops after main event', () => {
const testEvent = createMockEvent(
'Test',
{start: '2020-07-25', end: '2020-07-26'},
{start: '2020-07-27', end: '2020-07-27'});
it('should correctly format the main event date spanning mupliple days', () => {
const testEvent = createMockEvent('Test', {start: '2019-09-19', end: '2019-09-21'});
expect(component.getEventDates(testEvent)).toBe('September 19-21, 2019');
});
expect(component.getEventDates(testEvent))
.toBe('July 25-26 (conference), July 27 (workshops), 2020');
});
it('should correctly format the main event date spanning mupliple months', () => {
const testEvent = createMockEvent('Test', {start: '2019-10-30', end: '2019-11-01'});
expect(component.getEventDates(testEvent)).toBe('October 30 - November 1, 2019');
});
it('should correctly format event dates with workshops before main event', () => {
const testEvent = createMockEvent(
'Test',
{start: '2019-10-07', end: '2019-10-07'},
{start: '2019-10-06', end: '2019-10-06'});
expect(component.getEventDates(testEvent))
.toBe('October 6 (workshops), October 7 (conference), 2019');
});
it('should correctly format event dates spanning multiple days', () => {
const testEvent = createMockEvent(
'Test',
{start: '2019-08-30', end: '2019-08-31'},
{start: '2019-08-28', end: '2019-08-29'});
expect(component.getEventDates(testEvent))
.toBe('August 28-29 (workshops), August 30-31 (conference), 2019');
});
it('should correctly format event dates with workshops on different month before the main event',
() => {
const testEvent = createMockEvent(
'Test',
{start: '2020-08-01', end: '2020-08-02'},
{start: '2020-07-30', end: '2020-07-31'});
expect(component.getEventDates(testEvent))
.toBe('July 30-31 (workshops), August 1-2 (conference), 2020');
it('should correctly format event dates at the beginning/end of the year', () => {
const testEvent = createMockEvent('Test', {start: '2021-01-01', end: '2021-12-31'});
expect(component.getEventDates(testEvent)).toBe('January 1 - December 31, 2021');
});
});
it('should correctly format event dates with workshops on different month after the main event',
() => {
const testEvent = createMockEvent(
'Test',
{start: '2020-07-30', end: '2020-07-31'},
{start: '2020-08-01', end: '2020-08-02'});
describe('(with workshops)', () => {
it('should correctly format event dates with workshops after main event', () => {
const testEvent = createMockEvent(
'Test',
{start: '2020-07-25', end: '2020-07-26'},
{start: '2020-07-27', end: '2020-07-27'});
expect(component.getEventDates(testEvent))
.toBe('July 30-31 (conference), August 1-2 (workshops), 2020');
expect(component.getEventDates(testEvent))
.toBe('July 25-26 (conference), July 27 (workshops), 2020');
});
it('should correctly format event dates with workshops before main event', () => {
const testEvent = createMockEvent(
'Test',
{start: '2019-10-07', end: '2019-10-07'},
{start: '2019-10-06', end: '2019-10-06'});
expect(component.getEventDates(testEvent))
.toBe('October 6 (workshops), October 7 (conference), 2019');
});
it('should correctly format event dates spanning multiple days', () => {
const testEvent = createMockEvent(
'Test',
{start: '2019-08-30', end: '2019-08-31'},
{start: '2019-08-28', end: '2019-08-29'});
expect(component.getEventDates(testEvent))
.toBe('August 28-29 (workshops), August 30-31 (conference), 2019');
});
it('should correctly format event dates with workshops on different month before the main event',
() => {
const testEvent = createMockEvent(
'Test',
{start: '2020-08-01', end: '2020-08-02'},
{start: '2020-07-30', end: '2020-07-31'});
expect(component.getEventDates(testEvent))
.toBe('July 30-31 (workshops), August 1-2 (conference), 2020');
});
it('should correctly format event dates with workshops on different month after the main event',
() => {
const testEvent = createMockEvent(
'Test',
{start: '2020-07-30', end: '2020-07-31'},
{start: '2020-08-01', end: '2020-08-02'});
expect(component.getEventDates(testEvent))
.toBe('July 30-31 (conference), August 1-2 (workshops), 2020');
});
it('should correctly format event dates spanning multiple months', () => {
const testEvent = createMockEvent(
'Test',
{start: '2020-07-31', end: '2020-08-01'},
{start: '2020-07-30', end: '2020-08-01'});
expect(component.getEventDates(testEvent))
.toBe('July 30 - August 1 (workshops), July 31 - August 1 (conference), 2020');
});
});
it('should correctly format event dates spanning multiple months', () => {
const testEvent = createMockEvent(
'Test',
{start: '2020-07-31', end: '2020-08-01'},
{start: '2020-07-30', end: '2020-08-01'});
expect(component.getEventDates(testEvent))
.toBe('July 30 - August 1 (workshops), July 31 - August 1 (conference), 2020');
});
});
}
});
// Helpers

View File

@ -72,7 +72,7 @@ export class EventsComponent implements OnInit {
// If no work shop date create conference date string
dateString = processDate(event.date);
}
dateString = `${dateString}, ${new Date(event.date.end).getFullYear()}`;
dateString = `${dateString}, ${new Date(event.date.end).getUTCFullYear()}`;
return dateString;
}
}
@ -83,14 +83,14 @@ function processDate(dates: Duration) {
const endDate = new Date(dates.end);
// Create a date string in the start like January 31
let processedDate = `${MONTHS[startDate.getMonth()]} ${startDate.getDate()}`;
let processedDate = `${MONTHS[startDate.getUTCMonth()]} ${startDate.getUTCDate()}`;
// If they are in different months add the string '- February 2' Making the final string January 31 - February 2
if (startDate.getMonth() !== endDate.getMonth()) {
processedDate = `${processedDate} - ${MONTHS[endDate.getMonth()]} ${endDate.getDate()}`;
} else if (startDate.getDate() !== endDate.getDate()) {
if (startDate.getUTCMonth() !== endDate.getUTCMonth()) {
processedDate = `${processedDate} - ${MONTHS[endDate.getUTCMonth()]} ${endDate.getUTCDate()}`;
} else if (startDate.getUTCDate() !== endDate.getUTCDate()) {
// If not add - date eg it will make // January 30-31
processedDate = `${processedDate}-${endDate.getDate()}`;
processedDate = `${processedDate}-${endDate.getUTCDate()}`;
}
return processedDate;

View File

@ -13168,6 +13168,11 @@ timers-ext@^0.1.5:
es5-ext "~0.10.46"
next-tick "1"
timezone-mock@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/timezone-mock/-/timezone-mock-1.1.3.tgz#f5ca25befec2cdd2d64c07ee7a5293275c06b97e"
integrity sha512-r+fz9M1tflNkF6mJK0DwmlFyNWeSCXxZ68pu2Bv+DddIHK/czOZwnasEql17VfHqP/OcZRuPq/qi6wm7eQmQow==
timsort@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"