question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Refactor (and redesign?) parseDate()

See original GitHub issue

@iamkun Here is the issue with my comments, following the discussion in #417.

https://github.com/iamkun/dayjs/blob/a7e05e0b7fa529e8d81ebec3f007eb817d970fdd/src/index.js#L53-L61 Here I want to get rid of the warning eslint-disable-next-line no-cond-assign, I think that is not good style. Also, the check whether there is a z in the end of the string or not does not need to be a regex, which is also hinted by the comment looking for a better way. I propose these changes:

if (typeof date === 'string' && !date.toLowerCase().endsWith('z')) {
    const d = date.match(C.REGEX_PARSE)
    if (d) {
      return new Date(d[1], d[2] - 1, d[3] || 1, d[4] || 0, d[5] || 0, d[6] || 0, d[7] || 0)
    }
}

this also gets rid of the let reg in the first line of parseDate, moving the variable down where it is needed, renaming it to just d as reg was also quite inprecise as this is not a regex but rather matched parts of a date.

https://github.com/iamkun/dayjs/blob/a7e05e0b7fa529e8d81ebec3f007eb817d970fdd/src/index.js#L63

Here the comment is misleading. This is not the default return for timestamps only, but all of the following inputs will end up in this last return statement:

  • parseDate({}) // objects (invalid)
  • parseDate(function() {}) // function (invalid)
  • parseDate(Infinity) // non-finite number (invalid)
  • parseDate(12345) // finite number (valid, interpreted as unix timestamp)
  • parseDate('Mon Jan 01 2018 00:00:00 GMT+0100 (Mitteleuropäische Normalzeit)') // RFC 2822 date string (valid)
  • parseDate(() => '2018-01-01') // arrow func (valid in Chrome, invalid in Firefox)
  • parseDate([2018, 1, 1]) // Array (valid in both Firefox and Chrome!)

So I got two issues with this:

  • The comment is misleading and most of the cases I mention above are not explicitly tested by the dayjs test suite
  • We do not abstract the Date constructor default behavior, even causing incosistencies between different browsers

In my opinion, the second point is what I expect dayjs to do - provide a clear and straightforward API to create dates without any weird special cases. Instead almost everything is forwarded to the Date constructor, and adding more complexity even:

  • new Date(null) is fine in standard Javascript (and equivalent to new Date(0), so 1970-01-01T00:00:00.000, but null is not allowed with dayjs
  • dayjs also allows for all the moment.js special strings like 20180313 or 20180313 12:24:33
  • … but in other cases dayjs is not compatible with moment.js (e.g. moment({}) is now, where dayjs({}) is invalid)
  • most of the special cases (RFC2822 strings, momentjs-like-strings etc.) are not documented in the API documentation

So what is the overall design goal here? Should it be a 100% compatible with moment.js? Or should it abstract from weird browser behavior? Both is not given, and it might be confusing to the user.

Issue Analytics

  • State:open
  • Created 5 years ago
  • Comments:9 (8 by maintainers)

github_iconTop GitHub Comments

2reactions
suspectpartcommented, Feb 11, 2019

I pushed a PR to first refactor the code and write tests for everything that was not explicitly tested.

To make my second point clearer maybe: I have no specific proposal, I just think the dayjs parser specification has no clear specification.

a) You can parse almost anything the default Date() constructor defined in ECMASfript can parse, except for one value: null (Javascript will treat it as new Date(0)). So we are not 100% consistent with Javascripts Date parsing functionality b) You can parse some special strings that are not default Javascript, the specification taken from moment.js (so for example parseDate('20180501') or parseDate('2018-4-1 13:4:33') work). But it is not 100% consistent with moment.js, as the kind of broken regex in dayjs also matches these values as valid:

  • '2018-041 13:4:33' (mixed dash and no-dash for month and day)
  • '2018-041XXXXXXXXXXX13:4:33' (between date and time, everything except for numbers is allowed with a *) Those are not accepted by moment.js, so we have an incosistency. c) when falling through to the default constructor, we are again inconsistent with moment.js as moment.js for example treats the empty object as now (moment({})), but dayjs({}) treats the empty object as invalid

So my point is: dayjs is neither completely consistent with the ECMAScript specification nor with moment.js. We should think about what is allowed and what is forbidden and find a design rationale that gives orientation here. I think it would be a good idea to be at least completely consistent with moment.js, but that requires some breaking changes and a lot of additional tests.

0reactions
ghostcommented, Feb 12, 2019

see my comments in #487 of why we can’t put everything into new Date pls

Read more comments on GitHub >

github_iconTop Results From Across the Web

Refactor, Rewrite or Redesign? - Fail Fast, Move On
Refactoring is all about small changes to the way code has been written to reduce technical debt as the code and our understanding...
Read more >
What is Refactoring (Code Refactoring)? - TechTarget
Refactoring is the process of restructuring code, while not changing its original functionality. The goal of refactoring is to improve internal code by ......
Read more >
Code Refactoring Best Practices: When (and When Not) to Do It
Code refactoring is a process used in the DevOps philosophy that involves editing and cleaning up previously written code without changing ...
Read more >
Refactoring vs redesigning - UX Collective
We decided on refactoring instead of redesigning. We did a homogenization of the logo in terms of shape and color.
Read more >
Refactoring and Design Patterns
Refactoring is a controllable process of improving code without creating new functionality. Design Patterns are typical solutions to the commonly occurring ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found