Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Translate UTC time to arbitrary local time in Mongo J/S

I'm running a map reduce job in Mongo db.

The mapping function should map (e.g. count) events of certain nature to days in a certain time zone (the key of the map is calendar day). The time zone can be different, and is effectively an input parameter to the map/reduce job.

The time stored in the database objects is in UTC.

Example:

object1: time=78000
object2: time=86420

mapReduce(objects, tz='America/Los_Angeles')
would return: [{"1/1/1970" : 2}]

and

mapReduce(objects, tz='Europe/London')
would return: [{"1/1/1970":1},{"1/2/1970":1}]

on the same dataset.

The JavaScript Date object can perfectly convert any UTC time into a local time, but it seems to be limited to what's "current" time zone of the J/S environment. I can't seem to find a way to specify the time zone that I want the conversion to be in.

The conversion should account for DST, and preferably for leap seconds.

Is there anything that I can do to achieve this?

like image 758
Pawel Veselov Avatar asked Oct 11 '12 00:10

Pawel Veselov


People also ask

How to store UTC time in MongoDB?

new Date("<YYYY-mm-ddTHH:MM:ss>") specifies the datetime in the client's local timezone and returns the ISODate with the specified datetime in UTC. new Date("<YYYY-mm-ddTHH:MM:ssZ>") specifies the datetime in UTC and returns the ISODate with the specified datetime in UTC.

Does MongoDB use UTC?

MongoDB stores times in UTC by default, and will convert any local time representations into this form. Applications that must operate or report on some unmodified local time value may store the time zone alongside the UTC timestamp, and compute the original local time in their application logic.


1 Answers

I found the answer that will work for me. The scope, after all, was limited to having this support in server-side mongo DB, and only on Linux.

@AsyaKamsky pointed to a greate J/S library, timezone-js, that does full and proper time zone support, considering that it uses actual time zone files from IANA. However, loading arbitrary java-script libraries into Mongo server environment is not that easy. You can only load global function definitions. timezone-js also needs to be provided with a custom transport mechanism to download the timezone files (I don't even know if MongoDB server environment provides files access), or the time zone files have to be precompiled into JSON objects, and served along with the library. I decided that this would be too tedious of an approach, and I will have to be responsible of providing mechanism to update time zone files when they are changed.

The other alternative I was looking into - is hacking the J/S implementation used in Mongo to add a function that will do the job I want it to do. That is what I have done. Things are actually as dismal in the world of glibc as they are in JavaScript, but there is a library for the job, icu.

I've made this patch, that adds a static Date.daytz() function, which, taken a UTC timestamp, and a time zone name, will return a yyyy-mm-dd string.

Considering the following map/reduce functions:

fmap = function () {
    emit(Date.daytz(this.time * 1000, globtz), {count:1});
};
fred = function (k, v) {
    var r = {count:0};
    v.forEach(function (v0) {r.count += v0.count;});
    return r;
};

I get exactly what I wanted, running these two map reduce commands:

{ "mapreduce" : "objects",
    "map" : fmap,
    "reduce" : fred,
    "out" : { "inline" : 1 },
    "scope" : { "globtz" : "Europe/London" } }

and

{ "mapreduce" : "objects",
    "map" : fmap,
    "reduce" : fred,
    "out" : { "inline" : 1 },
    "scope" : { "globtz" : "America/Los_Angeles" } }
like image 111
Pawel Veselov Avatar answered Sep 22 '22 09:09

Pawel Veselov