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(datepicker): add DateAdapter and NativeDateAdapter #4148

Merged
merged 6 commits into from
Apr 20, 2017

Conversation

mmalerba
Copy link
Contributor

No description provided.

@mmalerba mmalerba requested a review from jelbourn April 19, 2017 01:39
@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Apr 19, 2017
* @param date The date to extract the day of the week from.
* @returns The month component (0-indexed, 0 = Sunday).
*/
abstract getDay(date: D): number;
Copy link
Member

Choose a reason for hiding this comment

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

Call this getDayOfTheWeek so that it can't possibly be mixed up with getDate?


/**
* Gets a list of names for the months.
* @param style The naming style (e.g. long = 'January', short = 'Jan', narrow = 'J').
Copy link
Member

Choose a reason for hiding this comment

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

style -> maybe format?

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 called it style because I don't want people confusing it with the format: any that they would pass to the parse or format functions

* @param date The date of month of the date.
* @returns The new date.
*/
abstract create(year: number, month: number, date: number): D;
Copy link
Member

Choose a reason for hiding this comment

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

Make this createDate so that in the future we can add createTime and createDatetime?

* @param locale The locale of the value.
* @returns The parsed date, or null if date could not be parsed.
*/
abstract parse(value: any, fmt?: any, locale?: any): D | null;
Copy link
Member

Choose a reason for hiding this comment

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

Should value not always be a string?

Can you elaborate more on what the format is meant to be here?

* @param amount The number of years, months, and days to add (may be negative).
* @returns A new date equal to the original with the given amount of time added.
*/
abstract add(date: D, amount: {years?: number, months?: number, days?: number}): D;
Copy link
Member

Choose a reason for hiding this comment

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

Related: https://momentjs.com/guides/#/lib-concepts/date-time-math/

amount -> timespan?

It's worth thinking about whether we want to separate the logic for adding "date spans" (years, months, days) versus "time spans" (maybe be hours, minutes, seconds, but eventually boils down to milliseconds). If not, then the single add could surprise people because the order of operations will affect the outcome. E.g., adding "1 month" will be a variable number of days based on where you are in the year. If it's broken up, then this method should probably be something like addDateSpan with addTimeSpan being added later.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm interesting... I assumed moment added years first then months then days, like how I do for Date, but it seems it does the opposite order. Do you think I should add largest unit first, smallest unit first, or only allow adding 1 unit at a time and force the user to determine the order?

Copy link
Member

Choose a reason for hiding this comment

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

Only adding one unit at a time is probably the only way to ensure that it does exactly what the user expects (e.g., addYears, addMonths, etc.). If we assume any kind of order of operations, I'd want to run a quick question by Google's i18n experts as to how they would say it should behave.

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'm also noticing that moment and closure seem to add what I'm calling 'calendarDays', 'calendarMonths', and 'calendarYears' here: https://github.com/angular/material2/blob/datepicker/src/lib/datepicker/calendar.ts#L271 I think I'll make add do that to be more in line with these other libraries

}


/** Adapts the native JS Date for use with material components that work with dates. */
Copy link
Member

Choose a reason for hiding this comment

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

Don't mention material specifically here since this will go in the cdk.

}

getMonthNames(style: 'long' | 'short' | 'narrow', locale?: any): string[] {
let dtf = new Intl.DateTimeFormat(locale, {month: style});
Copy link
Member

Choose a reason for hiding this comment

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

Since NativeDateAdapter will be the default if the user does nothing, we still have to support Intl not being available for Safari 9 (...probably? We should ask devrel for an opinion on this, since omitting the strings would be nice for payload size).

* @returns {boolean} Whether the two dates are equal.
* Null dates are considered equal to other null dates.
*/
equals(first: D | null, second: D | null): boolean {
Copy link
Member

Choose a reason for hiding this comment

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

Similar comment as above for equals and compare: you'll want different things for the time variants. Maybe just call them compareDate and sameDate?

expect(adapter.create(50, -12 * 51, 1).getFullYear()).toBe(-1);
});

it('should get today\'s date', () => {
Copy link
Member

Choose a reason for hiding this comment

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

optional: you can use double quotes (or template string backticks) when it's to avoid escaping single quotes

* @returns `min` if `date` is less than `min`, `max` if date is greater than `max`,
* otherwise `date`.
*/
clamp(date: D, min?: D | null, max?: D | null): D {
Copy link
Member

Choose a reason for hiding this comment

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

Same thing about date vs. time/datetime

@mmalerba mmalerba force-pushed the dp-date branch 2 times, most recently from 00c94de to d5aa3f3 Compare April 19, 2017 23:36
@mmalerba
Copy link
Contributor Author

comments addressed, PTAL

* @param fmt The format to use for the result string.
* @returns The parsed date, or null if date could not be parsed.
*/
abstract format(date: D, fmt?: any): string;
Copy link
Member

Choose a reason for hiding this comment

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

With this one format method, are we going to be able to get the different formats we need for date / time / datetime?

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 this should be ok Intl.DateTimeFormat, moment.js, and goog.date.Date all support this

* @returns A new date equal to the given date.
*/
clone(date: D): D {
return this.createDate(this.getYear(date), this.getMonth(date), this.getDate(date));
Copy link
Member

Choose a reason for hiding this comment

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

Would it be better to leave this without an implementation here so that the method can be used for all of date/time/datetime?

'October', 'November', 'December'
],
'short': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
'narrow': ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D']
Copy link
Member

Choose a reason for hiding this comment

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

By hard-coding the values into the return, you'll end up creating a new instance of these arrays each time the method is called. Move this object into a constant?

@@ -0,0 +1,242 @@
import {NativeDateAdapter} from './native-date-adapter';


Copy link
Member

Choose a reason for hiding this comment

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

In the material1 tests, I used constants for month indices to make the tests easier to read:

  // When constructing a Date, the month is zero-based. This can be confusing, since people are
  // used to seeing them one-based. So we create these aliases to make reading the tests easier.
  var JAN = 0, FEB = 1, MAR = 2, APR = 3, MAY = 4, JUN = 5, JUL = 6, AUG = 7, SEP = 8, OCT = 9,
      NOV = 10, DEC = 11;

Then your tests look like

expect(adapter.getYear(new Date(2017, JAN, 1))).toBe(2017);

Make a similar change here?

@mmalerba
Copy link
Contributor Author

comments addressed

Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

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

LGTM

@jelbourn jelbourn added pr: lgtm action: merge The PR is ready for merge by the caretaker and removed pr: needs review labels Apr 20, 2017
@mmalerba mmalerba merged commit 52400df into angular:datepicker Apr 20, 2017
mmalerba added a commit that referenced this pull request Apr 20, 2017
* added DateAdapter and NativeDateAdapter

* add tests

* addressed some comments

* more comments addressed

* another round of comments addressed

* add default formats
mmalerba added a commit that referenced this pull request Apr 29, 2017
* added DateAdapter and NativeDateAdapter

* add tests

* addressed some comments

* more comments addressed

* another round of comments addressed

* add default formats
mmalerba added a commit that referenced this pull request May 5, 2017
* added DateAdapter and NativeDateAdapter

* add tests

* addressed some comments

* more comments addressed

* another round of comments addressed

* add default formats
mmalerba added a commit that referenced this pull request May 9, 2017
* added DateAdapter and NativeDateAdapter

* add tests

* addressed some comments

* more comments addressed

* another round of comments addressed

* add default formats
@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 6, 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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants