最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Getting moment.js to show datetimes appropriate to info being viewed - Stack Overflow

programmeradmin0浏览0评论

Previous answers on here pointed me to moment.js for javascript date handling and I am really happy to find it. I can parse and manipulate quite happily.

The users on my website look at info relating to diverse physical sites/locations, and I want to show associated datetimes in the time specific to that location, not the users location.

Each physical site has a timezone attribute string like "Europe/London" or "Europe/Amsterdam"

My datetimes are all stored and delivered from the DB in UTC.

Is there a clever simple way I can render my moment.js object in any specified timezone?

Previous answers on here pointed me to moment.js for javascript date handling and I am really happy to find it. I can parse and manipulate quite happily.

The users on my website look at info relating to diverse physical sites/locations, and I want to show associated datetimes in the time specific to that location, not the users location.

Each physical site has a timezone attribute string like "Europe/London" or "Europe/Amsterdam"

My datetimes are all stored and delivered from the DB in UTC.

Is there a clever simple way I can render my moment.js object in any specified timezone?

Share Improve this question edited May 6, 2012 at 11:41 Andrei 56.7k10 gold badges91 silver badges112 bronze badges asked May 3, 2012 at 20:06 AitchAitch 94211 silver badges20 bronze badges 2
  • 2 No, but you could use github.com/mde/timezone-js to convert. See also this issue (github.com/timrwood/moment/issues/162) on the moment.js github tracker; some tz format behavior has been deprecated to to varying Date.toString() implementations; it also points to timezone-js. – Jason Clark Commented May 3, 2012 at 20:19
  • 1 I feared this might be the case and was somewhat in denial. moment.js is so elegant and small, it seems a travesty to pollute it with other libs. :-( – Aitch Commented May 3, 2012 at 20:28
Add a comment  | 

4 Answers 4

Reset to default 10

Theoretically, you could do something like this.

moment.fn.formatInZone = function(format, offset) {
    return this.clone().utc().add('hours', offset).format(format);
}

moment().formatInZone('HH:mm:ss', 7);
moment().formatInZone('HH:mm:ss', -7);

However, this requires that you know the correct offset, so it won't take into consideration daylight saving time.

If you want to display dates in ANOTHER timezone than the user is actually in, then you need to start looking into stuff like https://bitbucket.org/pellepim/jstimezonedetect (if you need to detect which timezone a user is in) and https://github.com/mde/timezone-js if you need to localize dates between zones.

jsTimezoneDetect which I linked to above will help you provide a shortlist of relevant timezones.

That you have your datetimes stored in UTC will make it pretty damn easy for you thanks to mde/timezone-js.

In node.js this is actually pretty simple using node-time (https://github.com/TooTallNate/node-time). Override the global Date object, then extend moment.js:

var time = require('time')(Date),
    moment = require('moment');

moment.fn.setTimezone = function(timezone, relative) {
    this.toDate().setTimezone(timezone, relative);
    return this;
}

moment.fn.getTimezone = function() {
    return this.toDate().getTimezone();
}

For good measure let's throw in a utility function to convert "incoming" date/time strings to UTC:

moment.fromTimezone = function(datetime, timezone) {
    return moment(datetime, "YYYY-MM-DD HH:mm").setTimezone(timezone, true).setTimezone("UTC");
}

And you can do this:

var fmt = "YYYY-MM-DD HH:mm",
    datetime = "2013-03-21 00:40",
    timezone = "Israel",
    m = moment.fromTimezone(datetime, timezone);

console.log(datetime, "in", timezone, "is", m.format(fmt), "in UTC");
console.log(m.format(fmt), "in UTC is", m.setTimezone(timezone).format(fmt), "in", m.getTimezone());

Shell output:

$ node mtz.js
2013-03-21 00:40 in Israel is 2013-03-20 22:40 in UTC
2013-03-20 22:40 in UTC is 2013-03-21 00:40 in Israel
$

About a year after this question was asked, Moment Timezone was introduced. Here's an example of how Moment Timezone can solve this problem.

const databaseDate = '2014-05-01T12:00:00Z';
const databaseTimezone = 'America/New_York';
const formatString = 'MMMM Do YYYY, h:mm:ss a';

const dateInUTC = moment.utc(databaseDate);
document.getElementById('dateInUTC').textContent = dateInUTC.format(formatString) + ' in UTC';


const dateInDbTZ = moment.utc(databaseDate).tz(databaseTimezone);
document.getElementById('dateInDbTZ').textContent = dateInDbTZ.format(formatString)  + ' in ' + databaseTimezone;

const dbDateWithoutTZ = '2014-05-01T12:00:00'; // no 'Z'
const dateInLocalTime = moment(dbDateWithoutTZ);
   document.getElementById('dateInLocalTime').textContent = dateInLocalTime.format(formatString) + ' in local time or ' + dateInLocalTime.utc().format(formatString) + ' in UTC';
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.17/moment-timezone-with-data.min.js"></script>
<dl>
<dt>UTC Date</dt>
<dd id="dateInUTC"></dd>
<dt>Timezone-formatted Date</dt>
<dd id="dateInDbTZ"></dd>
<dt>Bad: non-UTC date interpreted as "local time"</dt>
<dd id="dateInLocalTime"></dd>
</dl>

发布评论

评论列表(0)

  1. 暂无评论