Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue #1596 - Provide way to specify multiple formats when creating a date in UTC #1914

Open
wants to merge 25 commits into
base: dev
Choose a base branch
from

Conversation

BePo65
Copy link
Contributor

@BePo65 BePo65 commented May 27, 2022

The issue #1596 shows that the plugin 'customParseFormat' does not give a valid date, when used with utc parsing dates with offset.
I identified 2 interdependant reasons for this:

  1. customParseFormat.parse gives wrong arguments to dayjs when called by utc plugin with an array of formats.
    Details:
    calling utc(...) for parsing the utc plugin creates a cfg object with a correct 'utc' property ('true'); but the recursion in the parse function of 'customParseFormat' just transfers all the arguments to the call to 'dayjs' (const result = d.apply(this, args)). But the args property must be a cfg object.

  2. parsing a date with offset in strict mode always returns 'Invalid Date'.
    Details:
    (isStrict && date != this.format(format)) is an elegant way to find out, if the parsed date respects all the separators as defined in the format. But it fails, as soon as an offest comes into play; in this case the result of formatting the parsed date corresponds to the given format, but the used offset depends an the current local timezone and is not necessarily the same as the offset in the date to be parsed (e.g. '11:00+01' is the same as '12:00+02').
    As a result I had to change the way we identify a 'strict' match (including the handling of overflows in strict mode).

I did not squash the single commits, so that it is easier to analyze the single modifications.
The replacement for (isStrict && date != this.format(format)) (e.g. the part 'with offset' of the issue #1596) is in commit 69fdc94 and 158aed8; the commits 963b166 and 6a2974e just handle the 'with utc' part of issue #1596) and 52902e0 the self reference.
The rest are just tests for all the affected parsing scenarios.

@BePo65
Copy link
Contributor Author

BePo65 commented May 27, 2022

Perhaps we should add a list of the allowed separator characters (.-_:/() and any whitespace) to the customParseFormat plugin documentation ('https://day.js.org/docs/en/parse/string-format')? PR #1913 would add a comma to that list.

@BePo65
Copy link
Contributor Author

BePo65 commented May 27, 2022

And when we are at it, perhaps we should also add a list of the deviations from moment to the documentation:

title parameters dayjs moment
invalid date with overflow ('35/22/2010 99:88:77', 'DD-MM-YYYY HH:mm:ss') '08-11-2011 04:29:17' 'Invalid date'
invalid date with overflow, strict ('35/22/2010 99:88:77', 'DD-MM-YYYY HH:mm:ss', true) 'Invalid Date' 'Invalid date'
'0' day or month (using default values) ('1970-00-00', 'YYYY-MM-DD') '1970-01-01' 'Invalid date'
'0' day or month (using default values), strict ('1970-00-00', 'YYYY-MM-DD', true) 'Invalid Date' 'Invalid date'
date not matching format ('10/12/2014', 'YYYY-MM-DD') '01-01-2014' '12-20-2010'
date not matching format, strict ('10/12/2014', 'YYYY-MM-DD', true) 'Invalid Date' 'Invalid date'
first match vs. longest match ('2012-05-28 10:21:15', ['YYYY', 'YYYY-MM-DD', 'YYYY-MM-DD HH:mm:ss']) '2012-01-01 00:00:00' '2012-05-28 10:21:15'
first match vs. longest match, strict ('2012-05-28 10:21:15', ['YYYY', 'YYYY-MM-DD', 'YYYY-MM-DD HH:mm:ss'], true) '2012-05-28 10:21:15' '2012-05-28 10:21:15'

@BePo65
Copy link
Contributor Author

BePo65 commented May 28, 2022

Fixes issue #1331 too.
Fixes issue #1552 too.
Fixes issue #1616 too.
Fixes issue #1750 too.
Fixes issue #1902 too.

@BePo65
Copy link
Contributor Author

BePo65 commented May 29, 2022

I finally found the "older" pr #1467 that solves at least the issue with the offset in strict mode, when the format contains a Z token.

  • the pr fix: customParseFormat strict mode bug when parsing with timezones (#929) #1467 takes the approach of improving the way to identify a 'strict match' ('date != this.format(format)') while
  • this pr tries to identify 'strictness' while parsing the date parts; this method allows to fix other issues with parsing that occurred e.g. when the sequence of date parts did not match the sequence of format token e.a.

So now you have the choice :-)

@iamkun by now there are a lot of open issues and quite some pr. Is there a way I could help you to reduce the number of open issues and pr?

src/index.js Outdated Show resolved Hide resolved
@codecov
Copy link

codecov bot commented Jun 6, 2022

Codecov Report

Merging #1914 (9bf4076) into dev (7151139) will not change coverage.
The diff coverage is 100.00%.

❗ Current head 9bf4076 differs from pull request most recent head af75753. Consider uploading reports for the commit af75753 to get more accurate results

@@            Coverage Diff            @@
##               dev     #1914   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          181       184    +3     
  Lines         2074      2158   +84     
  Branches       544       579   +35     
=========================================
+ Hits          2074      2158   +84     
Impacted Files Coverage Δ
src/locale/fa.js 100.00% <ø> (ø)
src/index.js 100.00% <100.00%> (ø)
src/locale/en.js 100.00% <100.00%> (ø)
src/locale/fr.js 100.00% <100.00%> (ø)
src/locale/nl.js 100.00% <100.00%> (ø)
src/locale/zh-tw.js 100.00% <100.00%> (ø)
src/plugin/advancedFormat/index.js 100.00% <100.00%> (ø)
src/plugin/bigIntSupport/index.js 100.00% <100.00%> (ø)
src/plugin/customParseFormat/index.js 100.00% <100.00%> (ø)
src/plugin/customParseFormat/utils.js 100.00% <100.00%> (ø)
... and 3 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@iamkun
Copy link
Owner

iamkun commented Jun 7, 2022

thanks, please allow me some time to go through this cool PR

@BePo65
Copy link
Contributor Author

BePo65 commented Jun 7, 2022

You've got all the time in the world; if my documentation of the changes needs improvement, feel free to ask.

}

// eslint-disable-next-line import/prefer-default-export
export const daysInMonth = (year, month) => {
Copy link
Owner

@iamkun iamkun Jun 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can use the built-in API

dayjs(year + '-' + month).daysInMonth()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry for the late reply, but somehow I missed this comment :-(

Of course we could use dayjs(year + '-' + month).daysInMonth() instead of my 'auxiliary' method.

But the problem is that we do not have the dayjs object available to the checkOverflow() function.

Therefore I created the daysInMonth method in the customParseFormat/utils file.
As an additional bonus, this function runs faster than creating a new dayjs object (to be exact, more than 1 instance is created for getting daysInMonth).

What do you think about this?

@WikiRik
Copy link

WikiRik commented Mar 24, 2023

@BePo65 any chance you could update this PR soon? Or would you be fine if I tried to update it in a new PR?

BePo65 added 7 commits March 25, 2023 07:18
'd.apply' calls dayjs, which expects a config object as 2nd parameter;
otherwise it creates a new config object without utc property.
Using 'd.utc.apply' would call dayjs.utc, but cannot be used, if not
parsing as utc.
By setting 'args[1]' cfg is modified to include a single format; this
config already has a correctly set utc property.
CustomParseFormat.parse expects a string or an array as args parameter of
the cfg. When called recursively (via 'd.apply') dayjs added 'arguments'
which is of type object as cfg.args and therefore parse cannot access
e.g. the format as 'args[1]'.
The rest operator changes arguments to an array. And if dayjs gets a
config object with an args property as the 2nd parameter, we do not have
to add an args property, as everything is already in place.
When the 2nd paramater of dayjs() is a config object, just assigning
'arguments' to the args property will modify the original 'c' parameter
and thus create a self referencing property (does not change functionality,
but should be avoided).
As 'arguments' is of type 'object', we must handle the case 'dayjs() with
multiple formats array, but without utc' by taking care of 'c' of type
array.
@BePo65
Copy link
Contributor Author

BePo65 commented Mar 25, 2023

@BePo65 any chance you could update this PR soon? Or would you be fine if I tried to update it in a new PR?

I added 2 tests for your issue #1734 and found out that I missed a comment from @iamkun - replied to this comment too.

So now I hope we have everything in place so that the review of this pr can be completed. Let's hope the best 😄

@le0pard
Copy link

le0pard commented May 30, 2023

Is any help needed with this PR?

@WikiRik
Copy link

WikiRik commented May 31, 2023

@le0pard you can review this PR, but mostly we're waiting on a review by @iamkun

CHANGELOG.md Outdated
@@ -1,3 +1,11 @@
## [1.11.7](https://github.com/iamkun/dayjs/compare/v1.11.6...v1.11.7) (2022-12-06)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the changes to CHANGELOG.md should be reverted as they're not in scope for this PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line comes from dayjs 1.11.7 - the base of my pr and is autogenerated by the dayjs build system (I suppose). The line itself is the link to the git changes (as in any versions before). But you knew all this before 😄

So I don't know why this is a "changed file" here, as I didn't change it in my pr.
in the cuurent master branch (1.11.9) the line looks unchanged and AFAIK github should / could rebase a pr automatically on merge.
So what should I change in the changelog.md file?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub says these lines are added by your PR. Maybe if you rebase this PR to dev these changes would be removed since they are then already implemented

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, as this pr will merge to dev.
But.... somehow it looks like dev is not up to date, For me it looks like the dev branch somehow is stuck on v1.11.6, while master moved on to 1.11.9.

So I think / hope that all this mess will disappear, when this pr is merged into master (if this will ever happen :-)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you check out the dev from your fork by any chance? It seems that dev is the default branch of this repo and things have been merged to it a few days ago

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh man this is a mess with the branches in this repo:
master contains the line to v1.11.9 while dev is not up to date with master.

I think I will rebase the pr to dev as soon as @iamkun answers to my comment on his remark to 'utils.js' below.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants