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

feat(moment-dateadapter): add option to create utc dates #11336

Merged
merged 9 commits into from
Jun 27, 2018

Conversation

Silthus
Copy link
Contributor

@Silthus Silthus commented May 15, 2018

Moment DateAdapter should create dates in utc format to avoid time zone
collisions when passing date to servers.
To avoid a breaking change a new injection token MAT_MOMENT_DATE_ADAPTER_OPTIONS has been created with the option useUtc: boolean. The option defaults to false.

See #7167 (comment) for more details on the issue.

Closes #7167

Moment DateAdapter should create dates in utc format to avoid time zone
collisions when passing date to servers

Closes angular#7167
@Silthus Silthus requested a review from mmalerba as a code owner May 15, 2018 10:42
@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and have the pull request author add another comment and the bot will run again. If the bot doesn't comment, it means it doesn't think anything has changed.

@googlebot googlebot added the cla: no PR author must sign Google's Contributor License Agreement: https://opensource.google.com/docs/cla label May 15, 2018
@Silthus
Copy link
Contributor Author

Silthus commented May 15, 2018

I added the missing email addresses to my google and github account. CLA should be fine now.

@googlebot
Copy link

CLAs look good, thanks!

@googlebot googlebot added cla: yes PR author has agreed to Google's Contributor License Agreement and removed cla: no PR author must sign Google's Contributor License Agreement: https://opensource.google.com/docs/cla labels May 15, 2018
@mmalerba mmalerba added pr: lgtm action: merge The PR is ready for merge by the caretaker target: patch This PR is targeted for the next patch release labels May 15, 2018
@sir-boformer
Copy link
Contributor

Very welcome addition!

This will break existing apps which depend on the local date output.

@mmalerba mmalerba removed pr: lgtm action: merge The PR is ready for merge by the caretaker labels May 21, 2018
@mmalerba
Copy link
Contributor

I initially thought this was doing something similar to what we do in NativeDateAdapter where we re-create the date as a UTC date for display purposes only, but this is actually changing the format passed to and from the user. I don't think we want to make this change since it will break a lot of apps. If you need to pass the object to a server just call .utc() on the object passed back by the datepicker

@mmalerba mmalerba closed this May 21, 2018
@eitland
Copy link

eitland commented May 22, 2018

@mmalerba, thanks for looking into this, I think however the issue is more complicated.

My, and I think a number of others problem is that it parses wrong.

you say:

If you need to pass the object to a server just call .utc() on the object passed back by the datepicker

here is what moment js docs says:

moment().utc();

Sets a flag on the original moment to use UTC to display a moment instead of the original moment's time.

So when I click on the date 2018-05-19, the moment object arrives as "2018-01-18T23:00:00Z", i.e. it points to the wrong timestamp.

I don't think we want to make this change since it will break a lot of apps.

Very probably yes, but on the other hand I've also seen at least one other workaround similar to the one @Silthus proposes, and I'm going to have to implement something similar as well.

Could we have a UTCMomentDateAdapter in addition to the current MomentDateAdapter? Or maybe we could add a flag somehow?

@mmalerba
Copy link
Contributor

I see, we could do it as an option probably. We could create injectable a token like MAT_MOMENT_DATE_ADAPTER_OPTIONS which would be an object {useUtc: boolean}, default would be false, but setting it to true will enable the behavior you guys are looking for. I'll reopen this PR so @Silthus can make this change

@mmalerba mmalerba reopened this May 22, 2018
@Silthus
Copy link
Contributor Author

Silthus commented Jun 4, 2018

I still have this on my radar and will try to work on it this week 👍🏻

@Silthus Silthus changed the title fix(dateadapter): moment dates not in utc format feat(moment-dateadapter): add option to create utc dates Jun 5, 2018
Added MAT_MOMENT_DATE_ADAPTER_OPTIONS with the useUtc: boolean option to
parse dates as utc
The new option defaults to false and will not cause any breaking
changes.

Closes angular#7167
Describe how to set the MomentDateAdapter to parse dates as utc.
Describe the default behaviour of the MomentDateAdapter.
Add an example on how to configure MAT_MOMENT_DATA_ADAPTER_OPTIONS

Closes angular#7167
@Silthus
Copy link
Contributor Author

Silthus commented Jun 5, 2018

@mmalerba is it ok now like this?

deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS]
},
{
provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS,
Copy link
Contributor

Choose a reason for hiding this comment

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

@jelbourn do you think we should use a root or module provider for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Probably root, but my tests failed with just the 'root' keyword on the injection token. Not sure how to do that with the new angular 6 system.

Copy link
Member

Choose a reason for hiding this comment

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

Generally anything that doesn't depend on Overlay should be providedIn: 'root'

Copy link
Contributor

Choose a reason for hiding this comment

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

You should be able to use MAT_DATE_LOCALE as an example: https://github.com/angular/material2/blob/master/src/lib/core/datetime/date-adapter.ts#L13

And tests for it here: https://github.com/angular/material2/blob/master/src/lib/core/datetime/native-date-adapter.spec.ts

It looks like you set it up correctly... what error were you getting in the tests?

Only provide MAT_MOMENT_DATE_ADAPTER_OPTIONS in root
@@ -29,10 +29,6 @@ export * from './moment-date-formats';
provide: DateAdapter,
useClass: MomentDateAdapter,
deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I found why the tests did not work. Now with the MAT_MOMENT_DATE_ADAPTER_OPTIONS in the deps all tests pass.

@Silthus
Copy link
Contributor Author

Silthus commented Jun 6, 2018

@mmalerba should all be good now. The travis check failed because of a timeout to the edge browser.

Copy link
Contributor

@mmalerba mmalerba left a comment

Choose a reason for hiding this comment

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

Looks good, we just need to make the new constructor param optional so its not a breaking change

@@ -48,7 +73,8 @@ export class MomentDateAdapter extends DateAdapter<Moment> {
narrowDaysOfWeek: string[]
};

constructor(@Optional() @Inject(MAT_DATE_LOCALE) dateLocale: string) {
constructor(@Optional() @Inject(MAT_DATE_LOCALE) dateLocale: string,
@Inject(MAT_MOMENT_DATE_ADAPTER_OPTIONS) private options: MatMomentDateAdapterOptions) {
Copy link
Contributor

Choose a reason for hiding this comment

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

In order to make this not a breaking change for anyone who might be extending the MomentDateAdapter lets make this:

/** @deletion-target 8.0.0 make this param required */
@Optional() @Inject(MAT_MOMENT_DATE_ADAPTER_OPTIONS) private options?: MatMomentDateAdapterOptions

@@ -130,7 +156,12 @@ export class MomentDateAdapter extends DateAdapter<Moment> {
throw Error(`Invalid date "${date}". Date has to be greater than 0.`);
}

let result = moment({year, month, date}).locale(this.locale);
let result;
if (this.options.useUtc) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this.options && this.options.useUtc after making the change requested above

@Silthus
Copy link
Contributor Author

Silthus commented Jun 8, 2018

@mmalerba done

@eitland
Copy link

eitland commented Jun 13, 2018

@mmalerba care to look into it? This should solve an a real problem for many of us.

@mmalerba mmalerba added pr: lgtm action: merge The PR is ready for merge by the caretaker labels Jun 15, 2018
@kuncevic
Copy link
Contributor

Is it coming in the next release?

@mmalerba
Copy link
Contributor

@kuncevic It's ready to submit, but we need to check it against Google's codebase to make sure nothing breaks first

@sheikalthaf
Copy link

@mmalerba hi,
May i know when this pull request will be merged. This is one of my main feature which i lagging behind in my project

@josephperrott josephperrott added action: merge The PR is ready for merge by the caretaker and removed action: merge The PR is ready for merge by the caretaker labels Jun 27, 2018
@josephperrott josephperrott merged commit 9a85b9b into angular:master Jun 27, 2018
josephperrott pushed a commit to josephperrott/components that referenced this pull request Jun 27, 2018
@ghost
Copy link

ghost commented Jun 28, 2018

Will this also work with manually typed in dates? If not, what should be used for the parse.dateInput of MAT_DATE_FORMATS?

@ghost
Copy link

ghost commented Jun 28, 2018

I'm pretty sure that the parse function will need replacing with something like:

  parse(value: any, parseFormat: string | string[]): Moment | null {
    if (value && typeof value === 'string') {
      if (this.options && this.options.useUtc) {
        return moment.utc(value, parseFormat, this.locale, true);
      } else {
        return moment(value, parseFormat, this.locale, true);
      }
    }
    if (this.options && this.options.useUtc) {
      return value ? moment.utc(value).locale(this.locale) : null;
    } else {
      return value ? moment(value).locale(this.locale) : null;
    }
  }

There could be other places where moment will need replacing with moment.utc and maybe a neater way of replacing them all. Sorry for not submitting a pull request right now.

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement target: patch This PR is targeted for the next patch release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Day incorrect in datepicker
9 participants