From 0323cddd476180528468ca94b9c33db0d91e15af Mon Sep 17 00:00:00 2001 From: Daneryl Date: Thu, 27 May 2021 17:38:40 +0200 Subject: [PATCH] edge case for dates where timezone was different --- app/react/Forms/components/DatePicker.js | 13 ++++-- .../Forms/components/specs/DatePicker.spec.js | 43 +++++++++++++++---- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/app/react/Forms/components/DatePicker.js b/app/react/Forms/components/DatePicker.js index d32c114477f..4949ee97b77 100644 --- a/app/react/Forms/components/DatePicker.js +++ b/app/react/Forms/components/DatePicker.js @@ -4,15 +4,18 @@ import 'react-datepicker/dist/react-datepicker.css'; import DatePickerComponent from 'react-datepicker'; import PropTypes from 'prop-types'; import React, { Component } from 'react'; -import moment from 'moment'; +import moment from 'moment-timezone'; const removeOffset = (useTimezone, value) => { let datePickerValue = null; + const miliseconds = value * 1000; if (value) { - const newValue = moment.utc(value * 1000); + const newValue = moment.utc(miliseconds); if (!useTimezone) { - newValue.subtract(moment().utcOffset(), 'minute'); + // in order to get the system offset for the specific date we + // need to create a new not UTC moment object with the original timestamp + newValue.subtract(moment(moment(miliseconds)).utcOffset(), 'minutes'); } datePickerValue = parseInt(newValue.locale('en').format('x'), 10); @@ -25,7 +28,9 @@ const addOffset = (useTimezone, endOfDay, value) => { const newValue = moment.utc(value); if (!useTimezone) { - newValue.add(moment().utcOffset(), 'minute'); + // in order to get the proper offset moment has to be initialized with the actual date + // without this this always gets this moment offset + newValue.add(moment(value).utcOffset(), 'minutes'); } if (endOfDay) { diff --git a/app/react/Forms/components/specs/DatePicker.spec.js b/app/react/Forms/components/specs/DatePicker.spec.js index 53d8d745d66..16bb80493a0 100644 --- a/app/react/Forms/components/specs/DatePicker.spec.js +++ b/app/react/Forms/components/specs/DatePicker.spec.js @@ -31,14 +31,9 @@ describe('DatePicker', () => { input = component.find(DatePickerComponent); }; - const expectCorrectSelectedValue = () => { + it('should render a DatePickerComponent with the correct date transformed to local value', () => { render(); - const expectedSelectedValue = date.clone().subtract(moment().utcOffset(), 'minute'); - expect(input.props().selected).toBe(parseInt(expectedSelectedValue.format('x'), 10)); - }; - - it('should render a DatePickerComponent with the correct transformed to local value', () => { - expectCorrectSelectedValue(); + expect(input.props().selected).toBe(parseInt(moment('2016-07-28').format('x'), 10)); }); describe('when useTimezone is true', () => { @@ -62,6 +57,37 @@ describe('DatePicker', () => { expectCorrectOnChange(); }); + afterEach(() => { + moment.tz.setDefault(); + }); + + describe('when date is in a diferent timezone than today', () => { + it.each([ + { timezone: 'Japan', dateToTest: '1950-08-05' }, + { timezone: 'Europe/Madrid', dateToTest: '1973-08-18' }, + ])('should use the timestamp offsetting to UTC %s', ({ timezone, dateToTest }) => { + moment.tz.setDefault(timezone); + const newDate = moment.utc(dateToTest); + props.value = Number(newDate.format('X')); + + render(); + expect(input.props().selected).toBe(parseInt(moment(dateToTest).format('x'), 10)); + }); + + it.each([ + { timezone: 'Japan', dateToTest: '1950-08-05' }, + { timezone: 'Europe/Madrid', dateToTest: '1973-08-18' }, + ])('should set the value to timestamp offsetting to UTC %s', ({ timezone, dateToTest }) => { + moment.tz.setDefault(timezone); + const newDate = moment(dateToTest).toDate(); + render(); + input.simulate('change', newDate); + expect(props.onChange).toHaveBeenCalledWith( + parseInt(moment.utc(dateToTest).format('X'), 10) + ); + }); + }); + describe('When locale is a non-latin locale', () => { let originalLocale; @@ -75,7 +101,8 @@ describe('DatePicker', () => { }); it('should render a latin-based value (until correct locales are implemented)', () => { - expectCorrectSelectedValue(); + render(); + expect(input.props().selected).toBe(parseInt(moment('2016-07-28').format('x'), 10)); }); it('should not fail on change', () => {