Improved time formatting and conversion
Bunyan CLI was not handling timezone conversion properly when set to use local time. This patch uses [Moment.js][] to fix those issues. * Timezone conversions work properly across DST conversions * The timezone, when shown, is correctly shown as `±hh:mm` * The timzeone is omitted on short output, since it isn't that short. Except when UTC is used, since that can be indicated by the single character `Z` Fixes #245 [Moment.js]: http://momentjs.com/
This commit is contained in:
parent
c1662212f8
commit
8df86bccf0
4 changed files with 70 additions and 14 deletions
3
Makefile
3
Makefile
|
@ -18,7 +18,8 @@ ifeq ($(shell uname -s),Darwin)
|
||||||
endif
|
endif
|
||||||
NODEOPT ?= $(HOME)/opt
|
NODEOPT ?= $(HOME)/opt
|
||||||
|
|
||||||
|
# Run tests in a set timezone, so local time is predictable
|
||||||
|
export TZ=Pacific/Honolulu
|
||||||
|
|
||||||
#---- Files
|
#---- Files
|
||||||
|
|
||||||
|
|
38
bin/bunyan
38
bin/bunyan
|
@ -25,6 +25,7 @@ var child_process = require('child_process'),
|
||||||
exec = child_process.exec,
|
exec = child_process.exec,
|
||||||
execFile = child_process.execFile;
|
execFile = child_process.execFile;
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var moment = require('moment');
|
||||||
|
|
||||||
var nodeSpawnSupportsStdio = (
|
var nodeSpawnSupportsStdio = (
|
||||||
Number(process.version.split('.')[0]) >= 0 ||
|
Number(process.version.split('.')[0]) >= 0 ||
|
||||||
|
@ -87,6 +88,16 @@ Object.keys(levelFromName).forEach(function (name) {
|
||||||
TIME_UTC = 1; // the default, bunyan's native format
|
TIME_UTC = 1; // the default, bunyan's native format
|
||||||
TIME_LOCAL = 2;
|
TIME_LOCAL = 2;
|
||||||
|
|
||||||
|
// Timestamp formats. Timezone is added at format time
|
||||||
|
UTC_FORMATS = {
|
||||||
|
long: 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]',
|
||||||
|
short: 'HH:mm:ss.SSS[Z]'
|
||||||
|
};
|
||||||
|
LOCAL_FORMATS = {
|
||||||
|
long: 'YYYY-MM-DD[T]HH:mm:ss.SSSZ',
|
||||||
|
short: 'HH:mm:ss.SSS'
|
||||||
|
};
|
||||||
|
|
||||||
var timezoneOffsetMs; // used for TIME_LOCAL display
|
var timezoneOffsetMs; // used for TIME_LOCAL display
|
||||||
|
|
||||||
|
|
||||||
|
@ -752,25 +763,26 @@ function emitRecord(rec, line, opts, stylize) {
|
||||||
|
|
||||||
delete rec.v;
|
delete rec.v;
|
||||||
|
|
||||||
var time = rec.time;
|
var time = moment(rec.time);
|
||||||
|
// default to UTC
|
||||||
|
var zoneFormats;
|
||||||
switch (opts.timeFormat) {
|
switch (opts.timeFormat) {
|
||||||
case TIME_UTC:
|
|
||||||
break;
|
|
||||||
case TIME_LOCAL:
|
case TIME_LOCAL:
|
||||||
if (!timezoneOffsetMs) {
|
zoneFormats = LOCAL_FORMATS;
|
||||||
timezoneOffsetMs
|
break;
|
||||||
= (new Date(time)).getTimezoneOffset() * 60 * 1000;
|
default:
|
||||||
}
|
// default to UTC
|
||||||
time = new Date(
|
zoneFormats = UTC_FORMATS;
|
||||||
(new Date(time)).getTime() - timezoneOffsetMs).toISOString()
|
time.utc();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (short && rec.time[10] === 'T') {
|
if (short) {
|
||||||
// Presuming `time` is ISO8601 formatted, i.e. safe to drop date.
|
time = time.format(zoneFormats.short);
|
||||||
time = stylize(time.substr(11), 'XXX');
|
|
||||||
} else {
|
} else {
|
||||||
time = stylize('[' + time + ']', 'XXX');
|
// Is there any way to put square brackets in a moment format?
|
||||||
|
time = '[' + time.format(zoneFormats.long) + ']';
|
||||||
}
|
}
|
||||||
|
time = stylize(time, 'XXX');
|
||||||
delete rec.time;
|
delete rec.time;
|
||||||
|
|
||||||
var nameStr = rec.name;
|
var nameStr = rec.name;
|
||||||
|
|
|
@ -32,5 +32,8 @@
|
||||||
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "make test"
|
"test": "make test"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"moment": "^2.10.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,46 @@ test('cat simple.log', function (t) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
test('simple.log local long', function (t) {
|
||||||
|
exec(_('%s -o long -L %s/corpus/simple.log', BUNYAN, __dirname),
|
||||||
|
function (err, stdout, stderr) {
|
||||||
|
t.ifError(err)
|
||||||
|
t.equal(stdout,
|
||||||
|
'[2012-02-08T12:56:52.856-10:00] INFO: myservice/123 on example.com: '
|
||||||
|
+ 'My message\n');
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
test('simple.log utc long', function (t) {
|
||||||
|
exec(_('%s -o long %s/corpus/simple.log', BUNYAN, __dirname),
|
||||||
|
function (err, stdout, stderr) {
|
||||||
|
t.ifError(err)
|
||||||
|
t.equal(stdout,
|
||||||
|
'[2012-02-08T22:56:52.856Z] INFO: myservice/123 on example.com: '
|
||||||
|
+ 'My message\n');
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
test('simple.log local short', function (t) {
|
||||||
|
exec(_('%s -o short -L %s/corpus/simple.log', BUNYAN, __dirname),
|
||||||
|
function (err, stdout, stderr) {
|
||||||
|
t.ifError(err)
|
||||||
|
t.equal(stdout,
|
||||||
|
'12:56:52.856 INFO myservice: '
|
||||||
|
+ 'My message\n');
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
test('simple.log utc short', function (t) {
|
||||||
|
exec(_('%s -o short %s/corpus/simple.log', BUNYAN, __dirname),
|
||||||
|
function (err, stdout, stderr) {
|
||||||
|
t.ifError(err)
|
||||||
|
t.equal(stdout,
|
||||||
|
'22:56:52.856Z INFO myservice: '
|
||||||
|
+ 'My message\n');
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
test('simple.log with color', function (t) {
|
test('simple.log with color', function (t) {
|
||||||
exec(_('%s --color %s/corpus/simple.log', BUNYAN, __dirname),
|
exec(_('%s --color %s/corpus/simple.log', BUNYAN, __dirname),
|
||||||
function (err, stdout, stderr) {
|
function (err, stdout, stderr) {
|
||||||
|
|
Loading…
Reference in a new issue