Skip to content

Commit

Permalink
STCOM-1141 - timepicker - consider timezone when parsing time value (#…
Browse files Browse the repository at this point in the history
…2012)

* timepicker - consider timezone when parsing time value

* update changelog
  • Loading branch information
JohnC-80 authored and zburke committed Mar 30, 2023
1 parent 811e18c commit 425ac2f
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Change history for stripes-components

## 11.0.3 IN PROGRESS

* Timepicker considers timezone when parsing value prop. Refs STCOM-1141.

## [11.0.2](https://github.com/folio-org/stripes-components/tree/v11.0.2) (2023-03-15)
[Full Changelog](https://github.com/folio-org/stripes-components/compare/v11.0.1...v11.0.2)

Expand Down
21 changes: 15 additions & 6 deletions lib/Timepicker/Timepicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import IconButton from '../IconButton';
import TimeDropdown from './TimeDropdown';
import parseMeta from '../FormField/parseMeta';
import nativeChangeFieldValue from '../../util/nativeChangeFieldValue';
import { getLocaleDateFormat, removeDST } from '../../util/dateTimeUtils';
import { getLocaleDateFormat } from '../../util/dateTimeUtils';

// supplied a list of formats, moment will use the FIRST format in the list
// that can be successfully parsed.
Expand All @@ -34,14 +34,21 @@ const defaultParser = (value, timezone, timeFormat, intl) => { // eslint-disable
if (containsUTCOffset(value)) {
// if it has an offset, it probably came from the backend and
// can be expected to be utc (utc offset of 0) -
time = moment.utc(value, timeFormat).local();
// we contrive a date string to pass the value to moment
// without having to get too specific about an expected format(s)...
// if we didn't do this, it would need something like
// moment.tz(value, 'HH:mm:ss.sssZ', timezone);
// with expected format(s) as the 2nd parameter

const dateString = moment().format('YYYY-MM-DD');
time = moment.tz(`${dateString}T${value}`, timezone);
} else {
time = moment(value, timeFormat);
time = moment(value, timeFormat, timezone);
}

// entered value that's fewer characters than the expected format will pass through..
// e.g. '2' in an expected full string of '2:35 AM'
return time.isValid() ? removeDST(time.toISOString(), timeFormat) : value;
return time.isValid() ? time.format(timeFormat) : value;
};

// Not all parameter keys may be used in this function, but they are provided as a convenience for
Expand Down Expand Up @@ -125,6 +132,7 @@ const Timepicker = ({
const intlContext = useIntl();
const intl = intlProp || intlContext;
const [showDropdown, setShowDropdown] = useState(showTimepicker || false);
const timezone = useRef(timeZoneProp || intl.timeZone).current;
const timeFormat = useRef(
timeFormatProp ||
getLocaleDateFormat({
Expand All @@ -135,13 +143,13 @@ const Timepicker = ({
const [timePair, updateTimePair] = useState({
timeString: valueProp ? parser(
valueProp, // value
timeZoneProp || intl.timeZone, // timezone
timezone,
timeFormat, // uiFormat
intl
) : '',
formatted: valueProp ? outputFormatter({
value: valueProp,
timezone: timeZoneProp || intl.timeZone,
timezone,
formats: timeFormat.includes('A') ? twelveHourFormats : twentyFourHourFormats,
}) : ''
});
Expand Down Expand Up @@ -375,6 +383,7 @@ const Timepicker = ({
>
<SRStatus ref={srStatus} />
<TextField
id={testId}
{...inputProps}
value={timePair.timeString || ''}
inputRef={handleInputRef}
Expand Down
40 changes: 36 additions & 4 deletions lib/Timepicker/tests/Timepicker-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ describe('Timepicker', () => {

describe('parsing a value prop with a time offset (usually from backend)', () => {
const testTime = '10:00:00.000Z';
const expectedTime = moment.utc(testTime, 'HH:mm:ss.sssZ').local().format('H:mm A');
const expectedTime = moment.utc(testTime, 'HH:mm:ss.sssZ').format('H:mm A');
beforeEach(async () => {
await mountWithContext(
<Timepicker
Expand All @@ -166,7 +166,7 @@ describe('Timepicker', () => {

describe('Application level behavior', () => {
const initialTime = '10:00:00.000Z';
const expectedTime = moment.utc(initialTime, 'HH:mm:ss.sssZ').local().format('H:mm A');
const expectedTime = moment.utc(initialTime, 'HH:mm:ss.sssZ').format('H:mm A');
beforeEach(async () => {
await mountWithContext(
<TimepickerHarness
Expand Down Expand Up @@ -237,9 +237,41 @@ describe('Timepicker', () => {
));
});

describe('parsing a time with timeZone prop (Barbados) (RFF)', () => {
const tz = 'America/Barbados';
const testTime = moment().tz(tz).isDST() ? '15:20:00.000Z' : '16:20:00.000Z';
const expectedTime = moment.tz(testTime, 'HH:mm:ss.sssZ', tz).format('h:mm A');
beforeEach(async () => {
await mountWithContext(
<TimepickerHarness
initialValue={testTime}
timeZone={tz}
/>
);
});

it('displays expected time in the field', () => timepicker.has({ value: expectedTime }));
});

describe('parsing a time with timeZone prop (UTC) (RFF)', () => {
const tz = 'UTC';
const testTime = '15:20:00.000Z';
const expectedTime = moment.tz(testTime, 'HH:mm:ss.sssZ', tz).format('h:mm A');
beforeEach(async () => {
await mountWithContext(
<TimepickerHarness
initialValue={testTime}
timeZone={tz}
/>
);
});

it('displays expected time in the field', () => timepicker.has({ value: expectedTime }));
})

describe('Timedropdown', () => {
const initialTime = '10:00:00.000Z';
const expectedTime = moment.utc(initialTime, 'HH:mm:ss.sssZ').local().format('H:mm A');
const expectedTime = moment.utc(initialTime, 'HH:mm:ss.sssZ').format('H:mm A');
beforeEach(async () => {
await mountWithContext(
<div>
Expand Down Expand Up @@ -427,7 +459,7 @@ describe('Timepicker', () => {

it('should close the timepicker dropdown', () => timeDropdown.absent());

it('should leave the orinal value in the timepicker', () => timepicker.has({ value: expectedTime }));
it('should leave the original value in the timepicker', () => timepicker.has({ value: expectedTime }));
});
});
});
Expand Down

0 comments on commit 425ac2f

Please sign in to comment.