Момент берёт инфу о времени и временной зоне из ОС. Если он показывает что-то неправильно, то значит у тебя неверно настроена временная зона в ОС.
Пример: я изменил tz на парижскую (+01:00), но время выставил московское. Если запросить момента время, то он выдаст то, что установлено в системе: 2016-02-03T04:08:24+01:00. Время совпадает с московским, но неверная tz. Если же насильно установить временную зону в самом моменте, то он возьмёт системное время и tz и попытается перевести в локальное время для указанной tz. Таким образом, если установить московскую tz и снова запросить текущее время, момент выдаст 2016-02-03T06:13:17+03:00. Время сдвинулось, но tz верная.
Так что у тебя скорее всего в системе стоит tz +04:00, вот час и теряется.
Ну и да, время нужно хранить в UTC, а выводить на страницу в соответствии с часовым поясом пользователя. Часовой пояс можно уточнять у самого клиента.
Узнавать сдвиг в минутах относительно UTC можно так: moment().utcOffset()