Moment is now in maintenance mode. For vue we have already date-fns, but unification across all frontends is desired.
To make the migration as easy as possible we could try day.js as try.
Get rid of old moment library. This would benefit the longterm development of jhipster and reduce the bundle size for angular/react a lot.
[x] Checking this box is mandatory (this is just to show you read everything)
@atomfrede or @pascalgrimaud can you assign @qlereboursBS and me on this one to try to fix it please ?
@qlereboursBS needs to comment so I'd be able to assign to him too :)
Done @pascalgrimaud
Ok, so, we listed all the usages of moments or date fns in the project, to be able to find each very specific usage and check if DayJS or Date fns can replace them:
| File | Use case |Comment | With DayJS |
|----------------|-------------------------------|-----------------------------|--------|
|core.module.ts.ejs (15) |import | import * as moment from 'moment';
| import dayjs from 'dayjs'
|
|core.module.ts.ejs (105) |Substract date| moment().year() - 100
| dayjs().subtract(100, 'year')
|
|date-utils.ts.ejs (19) |import | import moment from 'moment';
| import dayjs from 'dayjs'
|
|date-utils.ts.ejs (24) | format date |moment(date).format(APP_LOCAL_DATETIME_FORMAT)
| dayjs(date).format(APP_LOCAL_DATETIME_FORMAT)
|
|date-utils.ts.ejs (27) | parse date | moment(date, APP_LOCAL_DATETIME_FORMAT_Z).toDate()
| dayjs(date, APP_LOCAL_DATETIME_FORMAT_Z).toDate()
and don't forget to add dayjs.extend(customParseFormat)
|
|date-utils.ts.ejs (29) | format |moment().startOf('day').format(APP_LOCAL_DATETIME_FORMAT)
| dayjs().startOf('day').format(APP_LOCAL_DATETIME_FORMAT)
|
|datepicker-adapter.ts.ejs (23) | import |import { Moment } from 'moment';
| There's a Dayjs
type but we're not sure its exported. | |
|datepicker-adapter.ts.ejs (24) | import |import * as moment from 'moment';
| import * as dayjs from 'dayjs'
|
|datepicker-adapter.ts.ejs (27) | Specific use |export class ... extends NgbDateAdapter<Moment> {
| There's a Dayjs
type but we're not sure its exported. | |
|datepicker-adapter.ts.ejs (28) | Typing |fromModel(date: Moment): NgbDateStruct
| There's a Dayjs
type but we're not sure its exported. | |
|datepicker-adapter.ts.ejs (29) | Check validity |moment.isMoment(date) && date.isValid()
| dayjs.isDayjs(date) && date.isValid()
|
|datepicker-adapter.ts.ejs (36) | typing |toModel(date: NgbDateStruct): Moment {
| There's a Dayjs
type but we're not sure its exported. |
|datepicker-adapter.ts.ejs (38) | Parse date |moment(date.year + '-' + date.month + '-' + date.day, 'YYYY-MM-DD')
|dayjs(date.year + '-' + date.month + '-' + date.day, 'YYYY-MM-DD')
|
|duration.pipe.ts.ejs (3) | import |import * as moment from 'moment';
| import * as dayjs from 'dayjs'
|
|duration.pipe.ts.ejs (11) | Specific use (duration) |return moment.duration(value).humanize();
| return dayjs.duration(value).humanize();
|
|DurationFormat.tsx.ejs (3) | import |import * as moment from 'moment';
|import * as dayjs from 'dayjs'
|
|DurationFormat.tsx.ejs (20) | Specific use (duration) |moment.duration(value).locale(locale).humanize();
| dayjs.duration(value).locale(locale).humanize();
|
|entity-management-update.component.ts.ejs (49)| import |import * as moment from 'moment';
| import * as dayjs from 'dayjs
|
|entity-management-update.component.ts.ejs (184) | Get current date |const today = moment().startOf('day');
|const today = dayjs().startOf('day');
|
|entity-management-update.component.ts.ejs (299)| Parse date | moment(this.editForm.get(['<%= fieldName %>'])!.value, DATE_TIME_FORMAT)
| dayjs(this.editForm.get(['<%= fieldName %>'])!.value, DATE_TIME_FORMAT)
|
|entity-management.service.spec.ts.ejs (27) | import | import * as moment from 'moment';
| import * as dayjs from 'dayjs'
|
|entity-management.service.spec.ts.ejs (44) | typing |moment.Moment
|There's a Dayjs
type but we're not sure its exported. |
|entity-management.service.spec.ts.ejs (58) | Current date |currentDate = moment();
| currentDate = dayjs();
|
|entity.model.ts.ejs - React (26) | typing |import { Moment } from 'moment';
| There's a Dayjs
type but we're not sure its exported. |
|entity.model.ts.ejs - Angular (26) | typing |import { Moment } from 'moment';
| There's a Dayjs
type but we're not sure its exported. |
|entity.service.ts.ejs - Angular (30) | import |import * as moment from 'moment';
| import * as dayjs from 'dayjs';
|
|entity.service.ts.ejs - Angular (118) | parse date |moment(res.body.<%= fields[idx].fieldName %>)
| dayjs(res.body.<%= fields[idx].fieldName %>)
|
|entity.service.ts.ejs - Angular (130) | parse date |moment(<%= entityInstance %>.<%= fields[idx].fieldName %>)
| dayjs(<%= entityInstance %>.<%= fields[idx].fieldName %>)
|
|generator-base-private.js (370)| Specific use |Selecting locales to keep in webpack.prod.js of Angular | DayJS doesn't work the same way because it doesn't have a webpack plugin to whitelist languages. By default only specified languages will be loaded. We'll create a file like dayjs.config.js that will contain as much import 'dayjs/locale/fr'
as there are languages. |
|generator-base-private.js (406) |Specific use |Selecting locales to keep in webpack.prod.js of React | Removed according to the previous comment |
|generator-base.js (567) |Specific use| The function getMomentLocaleId()
returns the given language id. Its using the field momentLocaleId
from LANGUAGES
of generator-constants
because some specific languages have specific language id, i.e: hy-am
for Armenian | Replace momentLocaleId
by dateLibLocaleId
and check if the list of localeId are the same on DayJS than on moment |
| package.json | Specific use | usage of moment
and moment-locales-webpack-plugin
| It will be removed because there's no need of a webpack plugin with DayJS |
| webpack.prod.js.ejs | Specific use | Uses moment-locales-webpack-plugin
to load the locales | It will be removed because there's no need of a webpack plugin with DayJS |
Date fns usage
| File | Kind of use |Comment | With DayJS |
|----------------|-------------------------------|-----------------------------|------|
| entity-update.component.spec.ts.ejs (35) | format date | import format
, to format date with DATE_TIME_LONG_FORMAT
format (line 133) | import * as dayjs from 'dayjs';
then dayjs.format(date, DATE_TIME_LONG_FORMAT)
|
| entity-update.component.spec.ts.ejs (36) | parse date | import parseISO
unused | Remove import because it's not used |
| entity-update.component.ts.ejs (49) | format date | format date with DATE_TIME_LONG_FORMAT
format (line 231) | replace import and then replace format(date, DATE_TIME_LONG_FORMAT)
with dayjs(date).format(DATE_TIME_LONG_FORMAT)
|
| entity-update.component.ts.ejs (50) | check validity | check if date is valid (line 230) | Remove the import and replace isValid(date)
by dayjs(date).isValid()
| entity-update.component.ts.ejs (51) | parse date | parse date with DATE_TIME_LONG_FORMAT
format (line 238, 246) | remove import and replace parse(event.target.value, DATE_TIME_LONG_FORMAT, new Date())
by dayjs(event.target.value, DATE_TIME_LONG_FORMAT)
|
| entity-update.component.spec.ts.ejs (36) | parse date | import parseISO
unused | Remove unused import |
| entity.service.spec.ts.ejs (26) | format date | format date with format DATE_FORMAT
or DATE_TIME_FORMAT
| Replace all format(a, b)
by dayjs(a).format(b)
|
| filters.ts.ejs (2) | format date | format date with format DATE_TIME_FORMAT
| replace format(new Date(value), DATE_TIME_FORMAT)
by dayjs(new Date(value)).format(DATE_TIME_FORMAT)
|
| filters.ts.ejs (2) | parse date | parsing date | replace parseISO(value)
by dayjs(value)
|
| filters.ts.ejs (2) | format duration | formats a duration: https://date-fns.org/v2.15.0/docs/formatDuration | dayjs.duration(value).humanize();
|
| filters.ts.ejs (3) | parse duration | Import of duration-fns to parse a duration (line 27) | Removed the import and use the previous line |
For the moment, DayJS seems to be a better replacement solution to us:
Don't hesitate to shate your perspective
We updated the table above, to add the replacement solutions with DayJS.
We're going to start implementing now
Good work. Looking forward to the result!
We have implemented DayJs in the generator.
We're starting to find all the use cases where a date is used to test the new solution :slightly_smiling_face:
Functionnal usages (checked if tested):
date-utils.ts.ejs#convertDateTimeFromServer
: Only for React, aims to convert a date from server to the clientdate-utils.ts.ejs#convertDateTimeToServer
: Only for React, aims to convert a date from client to serverdate-utils.ts.ejs#displayDefaultDateTime
: Only for React, aims to get the default date time for inputscore.module.ts.ejs
: Only for Angular, aims to set the datePicker's config (NgbDatepickerConfig
), to set minDate at -100 years from todaydatepicker-adapter.ts.ejs
: Only for Angular, it's used to convert date to map date formats between boostrap datepicker component and the modelduration.pipe.ts.ejs
: Only for Angular, define the behavior of the duration
pipe (| duration
), used in entity-management and entity-manage-details screensDurationFormat.tsx.ejs
: Only for Angular, aims to format a durationentity-management-update.component.ts.ejs
Only for Angular, aims to create the data from the form value, before saving, on the entity screensentity-management.service.spec.ts.ejs
: Only for Angular, initializes a date for testing purposeentity.service.ts.ejs#convertDateArrayFromServer
: Only for Angular, in entity's service, creates a dayjs date from server when working with a list of entityentity-update.component.spec.ts.ejs
: Only for Vue, when testing entity update screen, import vuejs only if there's a date field, and do assertionsentity-update.component.ts.ejs
: Only for Vue, in entity update screen, importing dayjs only if there's a date field in the entityentity.service.spec.ts.ejs
: Only for Vue, testing the serviceentity.service.ts.ejs#convertDateFromServer
: Only for Vue, in entity's service, creates a dayjs date from server filters.ts.ejs#formatDate
: Only for Vue, this filter is used in multiple screens like admin/tracker, user-management, entity-detailsfilters.ts.ejs#formatMillis
: Only for Vue, this filter is only used in admin/metrics screenfilters.ts.ejs#duration
: Only for Vue, this filter is used in entity.vue screen, entity-details.vue
Most helpful comment
For the moment, DayJS seems to be a better replacement solution to us:
Don't hesitate to shate your perspective