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

DateInput + Moment-Timezone incompatability #280

Closed
mfedderly opened this issue Nov 30, 2016 · 7 comments
Closed

DateInput + Moment-Timezone incompatability #280

mfedderly opened this issue Nov 30, 2016 · 7 comments

Comments

@mfedderly
Copy link
Contributor

mfedderly commented Nov 30, 2016

BLUF

Using Moment-Timezone's setDefault call, the DateInput UI becomes inconsistent.

Bug report

  • Package version(s): 1.1.0
  • Browser and OS versions: Mac OSX 10.11.6 / Chrome 54.0.2840.98 (64-bit)

Steps to reproduce

  1. Use moment-timezone to set a default timezone, which affects all usage of the global 'moment'.
  2. Create a <DateInput> element with a specific date
  3. Configure specific problematic combinations of moment timezone and browser timezone.

Actual behavior

Depending on moment-timezone's configured timezone, and the browser's local timezone, the formatted date disagrees with the calendar date. For instance, if moment-timezone is set to America/Los_Angeles and the browser's timezone is set to Hawaii. The formatted date is correct, but the calendar will show a day behind. This has further repercussions when trying to get the time out of onChange as well.

Expected behavior

The DateInput correctly handles the timezone disagreement between moment and date.

Possible solution

I have built some quick functions that convert from moment->date that correct for the timezone discrepancy. They should be equivalent to a noop if a default timezone has not been set. The Date being passed into the render <DatePicker> and returned into handleDateChange can be adjusted with the methods below. It is important to make sure that the DateInput value prop is in the same timezone as the the date returned to the onChange prop.

/**
 * Translate a moment into a Date object, adjusting the moment timezone into the local one
 */
export function toDateFromMoment(date: moment.Moment) {
    return new Date(
        date.year(),
        date.month(),
        date.date(),
        date.hours(),
        date.minutes(),
        date.seconds(),
        date.milliseconds()
    );
}

/**
 * Translate a Date object into a moment, adjusting the local timezone into the moment one
 */
export function toMomentFromDate(date: Date) {
    return moment([
        date.getFullYear(),
        date.getMonth(),
        date.getDate(),
        date.getHours(),
        date.getMinutes(),
        date.getSeconds(),
        date.getMilliseconds(),
    ]);
}
@giladgray
Copy link
Contributor

giladgray commented Dec 1, 2016

@mfedderly react-day-picker has its own support for localization, have you checked that out? Might need to make its localization settings match moment.timezone's.

http://react-day-picker.js.org/Localization.html

@mfedderly
Copy link
Contributor Author

@giladgray This isn't a localization problem, Date and Moment disagree on the actual unixtime values that they are representing when moment-timezone has a default timezone that isn't the browser's timezone.

@giladgray
Copy link
Contributor

this sounds like a time localization problem, which is all about timezones (not to be confused with language localization).

@mfedderly
Copy link
Contributor Author

Specifically, it is not a react-day-picker localization problem.

@giladgray
Copy link
Contributor

ok i see what's up now. submit a PR with your functions above!

@alearcy
Copy link

alearcy commented Dec 6, 2016

After update to 1.2.0 my DateInput doesn't work anymore...with ReduxForm I have a pure function component with DateInput:

const nextYears = new Date(2040, 12, 31);
const renderDate = ({ input, label, type, meta: { touched, error } }) => (
	<div className="input-margin-bottom date-fill">
		<label className="pt-label">{label}</label>
		<DateInput {...input} locale="it" format="DD-MM-YYYY" maxDate={nextYears} position={Position.BOTTOM_RIGHT} className="pt-fill" />
		<div className='text-danger'>{touched ? error : ''}</div>
	</div>
);

before update blueprintjs it wored, now it doesn't works and the error is:

Uncaught TypeError: date.getFullYear is not a function

and refer to:

this.fromDateToMoment = function (date) {
            return moment([
                date.getFullYear(),
                date.getMonth(),
                date.getDate(),
                date.getHours(),
                date.getMinutes(),
                date.getSeconds(),
                date.getMilliseconds(),
            ]);
        };

@adidahiya
Copy link
Contributor

@alearcy would you mind filing a new issue for that? we'll try to get it sorted out for the next release.

greglo pushed a commit to greglo/blueprint that referenced this issue Dec 12, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants