Skip to content

Commit 1c92ea2

Browse files
committed
Merge branch 'display-time-zone' of https://github.com/custora/react-datetime into custora-display-time-zone
2 parents 87a4ca3 + cbb253e commit 1c92ea2

File tree

6 files changed

+83
-5
lines changed

6 files changed

+83
-5
lines changed

DateTime.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ declare namespace ReactDatetimeClass {
7676
Whether to interpret input times as UTC or the user's local timezone.
7777
*/
7878
utc?: boolean;
79+
/*
80+
When specified, input time values will be displayed in the given time zone. Otherwise they will default
81+
to the user's local timezone (unless `utc` specified).
82+
*/
83+
displayTimeZone?: string;
7984
/*
8085
Callback trigger when the date changes. The callback receives the selected `moment` object as
8186
only parameter, if the date in the input is valid. If the date in the input is not valid, the

DateTime.js

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ var Datetime = createClass({
3030
onNavigateForward: TYPES.func,
3131
locale: TYPES.string,
3232
utc: TYPES.bool,
33+
displayTimeZone: TYPES.string,
3334
input: TYPES.bool,
3435
// dateFormat: TYPES.string | TYPES.bool,
3536
// timeFormat: TYPES.string | TYPES.bool,
@@ -177,14 +178,21 @@ var Datetime = createClass({
177178
}
178179
}
179180

180-
if ( nextProps.utc !== this.props.utc ) {
181+
if ( nextProps.utc !== this.props.utc || nextProps.displayTimeZone !== this.props.displayTimeZone ) {
181182
if ( nextProps.utc ) {
182183
if ( this.state.viewDate )
183184
updatedState.viewDate = this.state.viewDate.clone().utc();
184185
if ( this.state.selectedDate ) {
185186
updatedState.selectedDate = this.state.selectedDate.clone().utc();
186187
updatedState.inputValue = updatedState.selectedDate.format( formats.datetime );
187188
}
189+
} else if ( nextProps.displayTimeZone ) {
190+
if ( this.state.viewDate )
191+
updatedState.viewDate = this.state.viewDate.clone().tz(nextProps.displayTimeZone);
192+
if ( this.state.selectedDate ) {
193+
updatedState.selectedDate = this.state.selectedDate.clone().tz(nextProps.displayTimeZone);
194+
updatedState.inputValue = updatedState.selectedDate.tz(nextProps.displayTimeZone).format( formats.datetime );
195+
}
188196
} else {
189197
if ( this.state.viewDate )
190198
updatedState.viewDate = this.state.viewDate.clone().local();
@@ -384,8 +392,16 @@ var Datetime = createClass({
384392

385393
localMoment: function( date, format, props ) {
386394
props = props || this.props;
387-
var momentFn = props.utc ? moment.utc : moment;
388-
var m = momentFn( date, format, props.strictParsing );
395+
var m = null;
396+
397+
if (props.utc) {
398+
m = moment.utc(date, format, props.strictParsing);
399+
} else if (props.displayTimeZone) {
400+
m = moment.tz(date, format, props.displayTimeZone);
401+
} else {
402+
m = moment(date, format, props.strictParsing);
403+
}
404+
389405
if ( props.locale )
390406
m.locale( props.locale );
391407
return m;
@@ -420,8 +436,8 @@ var Datetime = createClass({
420436
// TODO: Make a function or clean up this code,
421437
// logic right now is really hard to follow
422438
var className = 'rdt' + (this.props.className ?
423-
( Array.isArray( this.props.className ) ?
424-
' ' + this.props.className.join( ' ' ) : ' ' + this.props.className) : ''),
439+
( Array.isArray( this.props.className ) ?
440+
' ' + this.props.className.join( ' ' ) : ' ' + this.props.className) : ''),
425441
children = [];
426442

427443
if ( this.props.input ) {

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ render: function() {
5050
| **open** | `boolean` | `null` | Whether to open or close the picker. If not set react-datetime will open the datepicker on input focus and close it on click outside. |
5151
| **locale** | `string` | `null` | Manually set the locale for the react-datetime instance. Moment.js locale needs to be loaded to be used, see [i18n docs](#i18n).
5252
| **utc** | `boolean` | `false` | When true, input time values will be interpreted as UTC (Zulu time) by Moment.js. Otherwise they will default to the user's local timezone.
53+
| **displayTImeZone** | `string` | `null` | When specified, input time values will be displayed in the given time zone. Otherwise they will default to the user's local timezone (unless `utc` specified).
5354
| **onChange** | `function` | empty function | Callback trigger when the date changes. The callback receives the selected `moment` object as only parameter, if the date in the input is valid. If the date in the input is not valid, the callback receives the value of the input (a string). |
5455
| **onFocus** | `function` | empty function | Callback trigger for when the user opens the datepicker. The callback receives an event of type SyntheticEvent. |
5556
| **onBlur** | `function` | empty function | Callback trigger for when the user clicks outside of the input, simulating a regular onBlur. The callback receives the selected `moment` object as only parameter, if the date in the input is valid. If the date in the input is not valid, the callback returned. |

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"license": "MIT",
4242
"peerDependencies": {
4343
"moment": ">=2.16.0",
44+
"moment-timezone": "^0.5.13",
4445
"react": ">=0.13",
4546
"react-dom": ">=0.13"
4647
},
@@ -67,6 +68,7 @@
6768
"jsdom": "^7.0.2",
6869
"mocha": "^3.2.0",
6970
"moment": ">=2.16.0",
71+
"moment-timezone": "^0.5.13",
7072
"pre-commit": "^1.1.3",
7173
"react": "^15.5.0",
7274
"react-addons-test-utils": ">=0.13",

react-datetime.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ declare module ReactDatetime {
5757
Whether to interpret input times as UTC or the user's local timezone.
5858
*/
5959
utc?: boolean;
60+
/*
61+
When specified, input time values will be displayed in the given time zone. Otherwise they will default
62+
to the user's local timezone (unless `utc` specified).
63+
*/
64+
displayTimeZone?: string;
6065
/*
6166
Callback trigger when the date changes. The callback receives the selected `moment` object as
6267
only parameter, if the date in the input is valid. If the date in the input is not valid, the

test/tests.spec.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import React from 'react'; // eslint-disable-line no-unused-vars
44
import moment from 'moment';
5+
import _momentTimezone from 'moment-timezone'; // eslint-disable-line no-unused-vars
56
import utils from './testUtils';
67
import Enzyme from 'enzyme';
78
import Adapter from 'enzyme-adapter-react-15';
@@ -877,6 +878,34 @@ describe('Datetime', () => {
877878
});
878879
});
879880

881+
it('displayTimeZone -> value should change format (undefined->America/New_York)', () => {
882+
const date = new Date(2000, 0, 15, 2, 2, 2, 2),
883+
momentDate = moment(date),
884+
component = utils.createDatetime({ value: momentDate }),
885+
displayTimeZone = (moment.tz.guess() === 'America/New_York' ? 'America/Los_Angeles' : 'America/New_York');
886+
887+
const valueBefore = utils.getInputValue(component);
888+
component.setProps({ displayTimeZone: displayTimeZone }, () => {
889+
const valueAfter = utils.getInputValue(component);
890+
891+
expect(valueBefore).not.toEqual(valueAfter);
892+
});
893+
});
894+
895+
it('displayTimeZone -> value should change format (America/New_York->undefined)', () => {
896+
const date = new Date(2000, 0, 15, 2, 2, 2, 2),
897+
momentDate = moment(date),
898+
displayTimeZone = (moment.tz.guess() === 'America/New_York' ? 'America/Los_Angeles' : 'America/New_York'),
899+
component = utils.createDatetime({ value: momentDate, displayTimeZone: displayTimeZone });
900+
901+
const valueBefore = utils.getInputValue(component);
902+
component.setProps({ displayTimeZone: undefined }, () => {
903+
const valueAfter = utils.getInputValue(component);
904+
905+
expect(valueBefore).not.toEqual(valueAfter);
906+
});
907+
});
908+
880909
it('locale -> picker should change language (viewMode=days)', () => {
881910
const component = utils.createDatetime({ viewMode: 'days', locale: 'nl' }),
882911
weekdaysBefore = component.find('.rdtDays .dow').map((element) =>
@@ -1195,6 +1224,26 @@ describe('Datetime', () => {
11951224
expect(utils.getInputValue(component)).toEqual(strDateUTC);
11961225
});
11971226

1227+
it('TZ value from local moment', () => {
1228+
const date = new Date(2000, 0, 15, 2, 2, 2, 2),
1229+
displayTimeZone = 'America/New_York',
1230+
momentDate = moment(date),
1231+
momentDateTZ = moment.tz(date, displayTimeZone),
1232+
strDateTZ = momentDateTZ.format('L') + ' ' + momentDateTZ.format('LT'),
1233+
component = utils.createDatetime({ value: momentDate, displayTimeZone: displayTimeZone });
1234+
expect(utils.getInputValue(component)).toEqual(strDateTZ);
1235+
});
1236+
1237+
it('TZ value from UTC moment', () => {
1238+
const date = new Date(2000, 0, 15, 2, 2, 2, 2),
1239+
displayTimeZone = 'America/New_York',
1240+
momentDateUTC = moment.utc(date),
1241+
momentDateTZ = moment.tz(date, displayTimeZone),
1242+
strDateTZ = momentDateTZ.format('L') + ' ' + momentDateTZ.format('LT'),
1243+
component = utils.createDatetime({ value: momentDateUTC, displayTimeZone: displayTimeZone });
1244+
expect(utils.getInputValue(component)).toEqual(strDateTZ);
1245+
});
1246+
11981247
it('invalid string value', (done) => {
11991248
const date = new Date(2000, 0, 15, 2, 2, 2, 2),
12001249
mDate = moment(date),

0 commit comments

Comments
 (0)