0

I have a UI that allows a user to create an event. When the user creates this event they select a date( and time) and separately they select a timezone (eg. 'America/New_York') for the event location.

I need to use the date (includes time) and the selected timezone (string) to create a UTC date. I'm not sure how to do this.

I thought about using getTimezoneOffset but doesn't this change depending on the time of year ( British Summer Time etc).

Update. I wasn't very clear in my explanation, so here is more detail:

User selects date and time of an event that is 'Jan 01 2017 07:00:00'. They then select the timeZone of 'America/New_York'. It's happening at 7am in New York but I'm in the UK.

When I do:

const formatDate = moment.tz( new Date('Jan 01 2017 07:00:00'), 'America/New_York' ).format(); //returns '2017-01-01T02:00:00-05:00'

if I convert this date in new york to my local date with:

new Date( formatDate ); // returns 'Sun Jan 01 2017 07:00:00 GMT+0000 (GMT)'

I want it to return a local date and time of 'Sun Jan 01 2017 12:00:00 GMT+0000 (GMT)'.

Ewan
  • 378
  • 3
  • 14
  • The only sensible way to handle time zones are geographic identifiers, such as "America/New_York". – Álvaro González Jun 01 '17 at 09:11
  • You mean `new Date().toISOString()`? - this will always be UTC – Emissary Jun 01 '17 at 09:11
  • There is no "utcOffset" method. There is [*getTimezoneOffset*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset) which returns the host offset in minutes, + for west and - for east (opposite to ISO 8601). – RobG Jun 01 '17 at 09:15
  • Date objects are UTC internally. The host offset it used to calculate the UTC time value and to generate "local" values using the non-UTC methods. If you want to get an equivalent time in any time zone, adjust the UTC time by the required amount, then use UTC methods to generate a string, see [*Calculating a date and time in another time zone*](https://stackoverflow.com/questions/32002670/calculating-a-date-and-time-in-another-time-zone). – RobG Jun 01 '17 at 09:19
  • If adding a new library is a possibility you could consider using [moment.js](https://momentjs.com). Then you just use moment.utc(date).format() passing JavaScript's Date as date – Marcin Zareba Jun 01 '17 at 09:25
  • @MarcinZareba, a new library is fine. However, how do I specify a timezone? I'm new to moment.js and timezones. – Ewan Jun 01 '17 at 09:32
  • @ÁlvaroGonzález that is what i have. I have a string that I need to use with the date to create a UTC date ISO 8601. – Ewan Jun 01 '17 at 09:34
  • @Ewan I think [moment-timezone](http://momentjs.com/timezone/) is what you need. In your case you can use [`moment.tz`](http://momentjs.com/timezone/docs/#/using-timezones/parsing-in-zone/) – VincenzoC Jun 01 '17 at 09:54

2 Answers2

1

From docs:

If you want an actual time zone -- time in a particular location, like America/Los_Angeles, consider moment-timezone.

This suggests the feature is not built-in into Moment.js itself but the other library should get it done:

var newYork    = moment.tz("2014-06-01 12:00", "America/New_York");
var losAngeles = newYork.clone().tz("America/Los_Angeles");
var london     = newYork.clone().tz("Europe/London");

newYork.format();    // 2014-06-01T12:00:00-04:00
losAngeles.format(); // 2014-06-01T09:00:00-07:00
london.format();     // 2014-06-01T17:00:00+01:00

Beware that you should still store the named time zone in another column, because there's no way to deduct it from the date stored in MySQL.

Álvaro González
  • 142,137
  • 41
  • 261
  • 360
  • This is close to what I want but not quite. – Ewan Jun 01 '17 at 11:28
  • 1
    You aren't following the code in the example. As soon as you insert a literal `new Date('...')` call you're left to JavaScript date API and you lose the advantages of using Moment. – Álvaro González Jun 01 '17 at 14:01
0

I did it in the end with the following:

const momentTimezone = require( 'moment-timezone' );
const DateWithOffset = require( 'date-with-offset' );

module.exports = function( date, timezone ) {

    const offset = momentTimezone.tz.zone( timezone ).offset( date );

    const newDate = new DateWithOffset( date.toUTCString(), ( 0 - offset ) );

    return newDate.toISOString();

};

There may be a better way of doing this, but this seems to work. I used the npm module date-with-offset which did the job required.

Ewan
  • 378
  • 3
  • 14