5

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?

Pawel Veselov
  • 3,996
  • 7
  • 44
  • 62
  • Have you seen this question: http://stackoverflow.com/questions/10087819/convert-date-to-another-timezone-in-javascript – Asya Kamsky Oct 11 '12 at 01:37
  • This is one of my few real complaints about Javascript: the lack of standardized date functionality that is actually useful. I hope someone comes up with an answer for you. – slashingweapon Oct 11 '12 at 01:38
  • The question Asya pointed to does seem to help. Just need to figure out a way to integrate timzoneJS into Mongo. Seems that it (timezoneJS) provides proper support, as it's using actual timezone definition files. – Pawel Veselov Oct 11 '12 at 01:56
  • @AsyaKamsky any pointers on how to pre-load JS sources into Mongo JS environment, considering? :) – Pawel Veselov Oct 11 '12 at 01:58
  • sure: load("source.js") is equivalent to including all of source.js – Asya Kamsky Oct 11 '12 at 14:35
  • @AsyaKamsky That would only load it into the client, won't it? At least according to mongo docs... – Pawel Veselov Oct 12 '12 at 21:42
  • ah yes - that's what I thought you were asking, how to include some js source before the js you run. You can define server side functions in javascript though. – Asya Kamsky Oct 12 '12 at 22:40

1 Answers1

5

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" } }
Pawel Veselov
  • 3,996
  • 7
  • 44
  • 62
  • that's great! why not submit it as a pull request to mongo? :) – Asya Kamsky Oct 12 '12 at 22:41
  • 1
    @AsyaKamsky This probably too limited of an application for submission, and will drag a lot of tail (namely, the huge ICU library). If there was another JS Date standard that Mongo was to adopt, I don't even mind trying to make into a submittable patch. – Pawel Veselov Oct 12 '12 at 23:01