Skip to content

Commit

Permalink
fix: convert to/from ISO dates
Browse files Browse the repository at this point in the history
  • Loading branch information
tomzemp committed Oct 11, 2024
1 parent ee426b4 commit 3cb3c26
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 17 deletions.
10 changes: 8 additions & 2 deletions i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"POT-Creation-Date: 2024-01-15T14:35:08.966Z\n"
"PO-Revision-Date: 2024-01-15T14:35:08.966Z\n"
"POT-Creation-Date: 2024-10-10T14:28:50.013Z\n"
"PO-Revision-Date: 2024-10-10T14:28:50.014Z\n"

msgid "Not authorized"
msgstr "Not authorized"
Expand Down Expand Up @@ -525,6 +525,12 @@ msgstr "No"
msgid "Clear"
msgstr "Clear"

msgid "Pick a date"
msgstr "Pick a date"

msgid "Pick a time"
msgstr "Pick a time"

msgid "Delete"
msgstr "Delete"

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"node": ">=14.0.0"
},
"resolutions": {
"@dhis2/multi-calendar-dates": "^1.1.0",
"@dhis2/multi-calendar-dates": "^1.3.2",
"@dhis2/ui": "^9.2.0",
"@dhis2/app-runtime": "^3.10.2"
}
Expand Down
20 changes: 17 additions & 3 deletions src/data-workspace/inputs/datetime-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import i18n from '@dhis2/d2-i18n'
import { Button, CalendarInput } from '@dhis2/ui'
import React, { useState } from 'react'
import { useField } from 'react-final-form'
import { useSetDataValueMutation, useUserInfo } from '../../shared/index.js'
import {
convertFromIso8601ToString,
convertToIso8601ToString,
useSetDataValueMutation,
useUserInfo,
} from '../../shared/index.js'
import styles from './inputs.module.css'
import { InputPropTypes } from './utils.js'

Expand Down Expand Up @@ -94,10 +99,19 @@ export const DateTimeInput = ({
onKeyDown={onKeyDown}
disabled={disabled}
readOnly={locked}
date={date}
date={
date === ''
? ''
: convertFromIso8601ToString(date, calendar)
}
calendar={calendar}
onDateSelect={(date) => {
const selectedDate = date?.calendarDateString ?? ''
const selectedDate = date?.calendarDateString
? convertToIso8601ToString(
date?.calendarDateString,
calendar
)
: ''
setDate(selectedDate)
handleChange({ date: selectedDate, time })
}}
Expand Down
58 changes: 54 additions & 4 deletions src/data-workspace/inputs/datetime-input.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ describe('date input field', () => {
expect(mutate.mock.calls[0][0]).toHaveProperty('value', '')
})

it('works with ethiopian calendar', async () => {
it('posts ISO date to backend with ethiopian calendar', async () => {
// this is 2016-02-30 Ethopian
jest.setSystemTime(new Date('2023-11-10T09:05:00.000Z'))

Expand Down Expand Up @@ -281,13 +281,38 @@ describe('date input field', () => {
fireEvent.change(timepicker, { target: { value: '12:34' } })

expect(mutate.mock.calls).toHaveLength(1)

// date is converted back to ISO equivalent before being sent to backend
expect(mutate.mock.calls[0][0]).toHaveProperty(
'value',
'2016-02-30T12:34'
'2023-11-10T12:34'
)
})

it('works with nepali calendar', async () => {
it('populates the ethiopian equivalent of the persisted ISO date', async () => {
jest.setSystemTime(new Date('2024-07-25T09:05:00.000Z'))

useConfig.mockReturnValue({
systemInfo: { calendar: 'ethiopian' },
})

// 2021-04-22 ISO = 2013-08-14 ethiopian
const { getByRole, getByTestId } = render(
<FormWrapper
initialValues={{ [DE]: { [COC]: '2021-04-22T13:17' } }}
>
<DateTimeInput {...props} />
</FormWrapper>
)

const calendarInput = getByRole('textbox')
expect(calendarInput.value).toBe('2013-08-14')

const timepicker = getByTestId('time-input')
expect(timepicker.value).toBe('13:17')
})

it('posts ISO date to backend with nepali calendar', async () => {
// this is 2080-02-32 Nepali
jest.setSystemTime(new Date('2023-06-15T09:05:00.000Z'))

Expand Down Expand Up @@ -330,9 +355,34 @@ describe('date input field', () => {
fireEvent.change(timepicker, { target: { value: '12:34' } })

expect(mutate.mock.calls).toHaveLength(1)

// date is converted back to ISO equivalent before being sent to backend
expect(mutate.mock.calls[0][0]).toHaveProperty(
'value',
'2080-02-32T12:34'
'2023-06-15T12:34'
)
})

it('populates the nepali equivalent of the persisted ISO date', async () => {
jest.setSystemTime(new Date('2024-07-25T09:05:00.000Z'))

useConfig.mockReturnValue({
systemInfo: { calendar: 'nepali' },
})

// 2021-04-22 ISO = 2078-01-09 ethiopian
const { getByRole, getByTestId } = render(
<FormWrapper
initialValues={{ [DE]: { [COC]: '2021-04-22T13:17' } }}
>
<DateTimeInput {...props} />
</FormWrapper>
)

const calendarInput = getByRole('textbox')
expect(calendarInput.value).toBe('2078-01-09')

const timepicker = getByTestId('time-input')
expect(timepicker.value).toBe('13:17')
})
})
23 changes: 23 additions & 0 deletions src/shared/date/conversion-functions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {
convertFromIso8601,
convertToIso8601,
} from '@dhis2/multi-calendar-dates'

const padWithZeros = (val, count) => String(val).padStart(count, '0')

export const convertFromIso8601ToString = (date, calendar) => {
const { year, eraYear, month, day } = convertFromIso8601(date, calendar)
const ISOyear = calendar === 'ethiopian' ? eraYear : year
return `${padWithZeros(ISOyear, 4)}-${padWithZeros(
month,
2
)}-${padWithZeros(day, 2)}`
}

export const convertToIso8601ToString = (date, calendar) => {
const { year, month, day } = convertToIso8601(date, calendar)
return `${padWithZeros(year, 4)}-${padWithZeros(month, 2)}-${padWithZeros(
day,
2
)}`
}
4 changes: 4 additions & 0 deletions src/shared/date/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ export { default as formatJsDateToDateString } from './format-js-date-to-date-st
export { default as useClientServerDate } from './use-client-server-date.js'
export { default as useClientServerDateUtils } from './use-client-server-date-utils.js'
export { default as useServerTimeOffset } from './use-server-time-offset.js'
export {
convertFromIso8601ToString,
convertToIso8601ToString,
} from './conversion-functions.js'
39 changes: 32 additions & 7 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2617,12 +2617,22 @@
i18next "^10.3"
moment "^2.24.0"

"@dhis2/d2-i18n@^1.1.3":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@dhis2/d2-i18n/-/d2-i18n-1.1.3.tgz#ad73030f7cfceeed1b5bcaad86a9b336130bdfb1"
integrity sha512-vOu6RDNumOJM396mHt35bETk9ai9b6XJyAwlUy1HstUZNvfET61F8rjCmMuXZU6zJ8ELux8kMFqlH8IG0vDJmA==
dependencies:
"@types/i18next" "^11.9.0"
i18next "^10.3"
moment "^2.24.0"

"@dhis2/[email protected]", "@dhis2/multi-calendar-dates@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@dhis2/multi-calendar-dates/-/multi-calendar-dates-1.1.0.tgz#897d27eefa70eb60d3e8e72348f09ee739755ebb"
integrity sha512-VAuq3dIcI42mt1pCL3Xp9pebAOpUEz2ngShTIPD1ll7oMeanRAXkweBT1gburc5W3SfD6jbS8GuwemJ4zg4d3Q==
version "1.3.2"
resolved "https://registry.yarnpkg.com/@dhis2/multi-calendar-dates/-/multi-calendar-dates-1.3.2.tgz#34e5896f7fdfb761a2ee6035d848cba00446cde5"
integrity sha512-H37EptumkqZeHUpbR4wl3y2NZjeipxUNUI2VaHX28z2fbVD7O9H+k1InSskeP5nNWzTLMdPAM4lt/zQP8oRbrg==
dependencies:
"@js-temporal/polyfill" "^0.4.2"
"@dhis2/d2-i18n" "^1.1.3"
"@js-temporal/polyfill" "0.4.3"
classnames "^2.3.2"

"@dhis2/prop-types@^3.0.0-beta.1", "@dhis2/prop-types@^3.1.2":
Expand Down Expand Up @@ -3257,7 +3267,7 @@
"@jridgewell/resolve-uri" "3.1.0"
"@jridgewell/sourcemap-codec" "1.4.14"

"@js-temporal/polyfill@^0.4.2":
"@js-temporal/[email protected].3":
version "0.4.3"
resolved "https://registry.yarnpkg.com/@js-temporal/polyfill/-/polyfill-0.4.3.tgz#e8f8cf86745eb5050679c46a5ebedb9a9cc1f09b"
integrity sha512-6Fmjo/HlkyVCmJzAPnvtEWlcbQUSRhi8qlN9EtJA/wP7FqXsevLLrlojR44kzNzrRkpf7eDJ+z7b4xQD/Ycypw==
Expand Down Expand Up @@ -3850,6 +3860,11 @@
dependencies:
"@types/node" "*"

"@types/i18next@^11.9.0":
version "11.9.3"
resolved "https://registry.yarnpkg.com/@types/i18next/-/i18next-11.9.3.tgz#04d84c6539908ad69665d26d8967f942d1638550"
integrity sha512-snM7bMKy6gt7UYdpjsxycqSCAy0fr2JVPY0B8tJ2vp9bN58cE7C880k20PWFM4KXxQ3KsstKM8DLCawGCIH0tg==

"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44"
Expand Down Expand Up @@ -5632,11 +5647,16 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"

[email protected], classnames@^2.2.6, classnames@^2.3.1, classnames@^2.3.2:
[email protected], classnames@^2.2.6, classnames@^2.3.1:
version "2.3.2"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924"
integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==

classnames@^2.3.2:
version "2.5.1"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==

clean-css@^5.2.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.2.tgz#70ecc7d4d4114921f5d298349ff86a31a9975224"
Expand Down Expand Up @@ -14983,11 +15003,16 @@ tslib@^1.8.1, tslib@^1.9.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==

tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1:
tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==

tslib@^2.3.1:
version "2.7.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01"
integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==

tsutils@^3.21.0:
version "3.21.0"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
Expand Down

0 comments on commit 3cb3c26

Please sign in to comment.