1

I would like to understand Moment JS' initialisation of its moment object.

For example, if I would like to create a moment for the date and time: April 1 2000, 3:25:00 am with utc offset of +8 hours from UTC/GMT.

I represent this in a javascript object:

var obj = {
    year: 2000,
  month: 4, //APRIL
  day: 1,
  hour: 3,
  minute: 25,
  second: 0,
  utcOffset: 8  //8 hours from UTC
}

I then create a handy function I can use to create a moment with moment js:

var makemoment = function(obj){

  var m = moment([obj.year, obj.month - 1, obj.day, obj.hour, obj.minute, obj.second, 0]).utcOffset(obj.utcOffset);

  return m;
}

When I use this function to create moment... e.g.

  var result =  moment(obj);

If I inspect the result object above I can see that it has a property _d that I expect to have a value such as:

_d  Date {Sat Apr 01 2000 03:25:00 GMT+0800 (HKT)}

But the actual value is which for me does not make sense since I specified that the time is 3:25:00 and it is already at GMT +0800 so no need to add 8 hours to the time....

_d  Date {Sat Apr 01 2000 11:25:00 GMT+0800 (HKT)}

Despite of this _d value though, if I console.log(result) I get the correct expected date:

2000-04-01T03:25:00+08:00

If I call the utc method on the moment. e.g. result.utc() and if I inspect the object again, I can see that now the _d has changed to my originally expected value:

_d  Date {Sat Apr 01 2000 03:25:00 GMT+0800 (HKT)}

However, now if I do result.format() I get the correct UTC date and time:

2000-03-31T19:25:00+00:00

Am I not understanding something here???? How is the _d value used in Moment.js??? Should I ignore the _d value since it is just something internal to Moment.js???

I've created JSFiddle for to illustrate my point...

http://jsfiddle.net/nx2ch4ot/2/

1 Answer 1

2

A few things:

  • It's a common convention in JavaScript that fields of an object that are prefixed by an underscore are meant to be treated as private/internal and not used directly. Though it may be more user-friendly to hide them via closures, it's also slower, and thus libraries like moment.js choose to leave them exposed.

  • Instead of using _d, call a public function such as .format(), or any of the others shown in the documentation.

  • If you really want to know more about _d, take a look at this answer.

  • The time zone shown in a Date object will always be relative to the computer where the code is running. JavaScript's Date object doesn't have the ability to reflect other time zones. When moment uses _d, it mostly uses it just for its instantaneous value given by _d.getTime(), which reflects only UTC. (We're actually considering removing _d entirely in a future version.)

  • You do indeed need to adjust for the offset, but you should be starting from moment.utc instead of local time. The corrected function is:

    var makemoment = function(obj){
    
      var m = moment.utc([obj.year, obj.month - 1, obj.day, obj.hour, obj.minute, obj.second, 0]);
      m.subtract(obj.utcOffset, 'hours');
      m.utcOffset(obj.utcOffset);
    
      return m;
    }
    
  • The function you wrote is very similar to the one already built in to moment. You can pass an object to either moment or moment.utc. The difference with yours is that moment's uses zero-based months, and doesn't yet support passing a utcOffset field. You might just consider using that instead.

    var makemoment = function(obj){
    
      obj.month--; // switch to zero-based months
      var m = moment.utc(obj);
      obj.month++; // put it back
    
      m.subtract(obj.utcOffset, 'hours');
      m.utcOffset(obj.utcOffset);
    
      return m;
    }
    
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.