Commit ca1c60d7 authored by Simon Knox's avatar Simon Knox Committed by Natalia Tepluhina

Always show iterations in UTC time

The start/due dates for iterations are in UTC, but
formatDate was converting to user's local timezone.
For people in sub-zero timezones, midnight UTC is
the previous day for them
parent 8fc065bc
...@@ -89,13 +89,15 @@ export const getDayName = date => ...@@ -89,13 +89,15 @@ export const getDayName = date =>
* @example * @example
* dateFormat('2017-12-05','mmm d, yyyy h:MMtt Z' ) -> "Dec 5, 2017 12:00am GMT+0000" * dateFormat('2017-12-05','mmm d, yyyy h:MMtt Z' ) -> "Dec 5, 2017 12:00am GMT+0000"
* @param {date} datetime * @param {date} datetime
* @param {String} format
* @param {Boolean} UTC convert local time to UTC
* @returns {String} * @returns {String}
*/ */
export const formatDate = (datetime, format = 'mmm d, yyyy h:MMtt Z') => { export const formatDate = (datetime, format = 'mmm d, yyyy h:MMtt Z', utc = false) => {
if (isString(datetime) && datetime.match(/\d+-\d+\d+ /)) { if (isString(datetime) && datetime.match(/\d+-\d+\d+ /)) {
throw new Error(__('Invalid date')); throw new Error(__('Invalid date'));
} }
return dateFormat(datetime, format); return dateFormat(datetime, format, utc);
}; };
/** /**
......
...@@ -100,7 +100,7 @@ export default { ...@@ -100,7 +100,7 @@ export default {
}, },
methods: { methods: {
formatDate(date) { formatDate(date) {
return formatDate(date, 'mmm d, yyyy'); return formatDate(date, 'mmm d, yyyy', true);
}, },
}, },
}; };
......
...@@ -15,7 +15,7 @@ export default { ...@@ -15,7 +15,7 @@ export default {
}, },
methods: { methods: {
formatDate(date) { formatDate(date) {
return formatDate(date, 'mmm d, yyyy'); return formatDate(date, 'mmm d, yyyy', true);
}, },
}, },
}; };
......
import IterationsList from 'ee/iterations/components/iterations_list.vue'; import IterationsList from 'ee/iterations/components/iterations_list.vue';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import timezoneMock from 'timezone-mock';
describe('Iterations list', () => { describe('Iterations list', () => {
let wrapper; let wrapper;
...@@ -13,6 +14,7 @@ describe('Iterations list', () => { ...@@ -13,6 +14,7 @@ describe('Iterations list', () => {
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null; wrapper = null;
timezoneMock.unregister();
}); });
it('shows empty state', () => { it('shows empty state', () => {
...@@ -21,14 +23,15 @@ describe('Iterations list', () => { ...@@ -21,14 +23,15 @@ describe('Iterations list', () => {
expect(wrapper.html()).toHaveText('No iterations to show'); expect(wrapper.html()).toHaveText('No iterations to show');
}); });
it('shows iteration', () => { describe('with iterations', () => {
const iteration = { const iteration = {
id: '123', id: '123',
title: 'Iteration #1', title: 'Iteration #1',
startDate: '2020-05-27', startDate: '2020-05-27',
dueDate: '2020-05-28', dueDate: '2020-06-04',
}; };
it('shows iteration', () => {
mountComponent({ mountComponent({
iterations: [iteration], iterations: [iteration],
}); });
...@@ -36,4 +39,16 @@ describe('Iterations list', () => { ...@@ -36,4 +39,16 @@ describe('Iterations list', () => {
expect(wrapper.html()).not.toHaveText('No iterations to show'); expect(wrapper.html()).not.toHaveText('No iterations to show');
expect(wrapper.html()).toHaveText(iteration.title); expect(wrapper.html()).toHaveText(iteration.title);
}); });
it('displays dates in UTC time, regardless of user timezone', () => {
timezoneMock.register('US/Pacific');
mountComponent({
iterations: [iteration],
});
expect(wrapper.html()).toHaveText('May 27, 2020');
expect(wrapper.html()).toHaveText('Jun 4, 2020');
});
});
}); });
import { __, s__ } from '~/locale'; import { __, s__ } from '~/locale';
import $ from 'jquery'; import $ from 'jquery';
import timezoneMock from 'timezone-mock';
import '~/commons/bootstrap'; import '~/commons/bootstrap';
import * as datetimeUtility from '~/lib/utils/datetime_utility'; import * as datetimeUtility from '~/lib/utils/datetime_utility';
...@@ -86,6 +87,31 @@ describe('Date time utils', () => { ...@@ -86,6 +87,31 @@ describe('Date time utils', () => {
datetimeUtility.formatDate('2016-07-23 00:00:00 UTC'); datetimeUtility.formatDate('2016-07-23 00:00:00 UTC');
}).toThrow(new Error('Invalid date')); }).toThrow(new Error('Invalid date'));
}); });
describe('convert local timezone to UTC with utc parameter', () => {
const midnightUTC = '2020-07-09';
const format = 'mmm d, yyyy';
beforeEach(() => {
timezoneMock.register('US/Pacific');
});
afterEach(() => {
timezoneMock.unregister();
});
it('defaults to false', () => {
const formattedDate = datetimeUtility.formatDate(midnightUTC, format);
expect(formattedDate).toBe('Jul 8, 2020');
});
it('converts local time to UTC if utc flag is true', () => {
const formattedDate = datetimeUtility.formatDate(midnightUTC, format, true);
expect(formattedDate).toBe('Jul 9, 2020');
});
});
}); });
describe('get day difference', () => { describe('get day difference', () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment