/**
* DatetimeTransform defines a transformation on time or dates with timezones
*
* @class DatetimeTransform
*/
var AmpersandModel = require('ampersand-model');
var moment = require('moment-timezone');
var util = require('../util/time');
var misval = require('../util/misval');
module.exports = AmpersandModel.extend({
props: {
/**
* Timezone to use when parsing, for when timezone information is absent or incorrect.
* @memberof! DatetimeTransform
* @type {string}
*/
zone: ['string', true, 'ISO8601'],
/**
* Format indentifier to use when parsing, when not in ISO8601 format
* Mappings are defined in util/time.js => timeParts.description
* @memberof! DatetimeTransform
* @type {string}
*/
format: ['string', true, 'ISO8601'],
/**
* Reformats to a string using the momentjs or postgreSQL format specifiers.
* This allows a transformation to day of the year, or day of week etc.
* @memberof! DatetimeTransform
* @type {string}
*/
transformedFormat: ['string', true, 'ISO8601'],
/**
* Controls conversion to duration by subtracting this date
* @memberof! DatetimeTransform
* @type {string}
*/
transformedReference: 'string',
/**
* Reference timezone for conversion from datetime to duration
* @memberof! DatetimeTransform
* @type {string}
*/
transformedZone: ['string', true, 'ISO8601']
},
derived: {
// reference momentjs for duration <-> datetime conversion
referenceMoment: {
deps: ['transformedReference', 'transformedZone'],
fn: function () {
var tz;
if (this.transformedZone === 'ISO8601') {
tz = moment.tz.guess();
} else {
var timeZone = util.timeZones.get(this.transformedZone, 'description');
if (timeZone && timeZone.format) {
tz = timeZone.format;
} else {
tz = moment.tz.guess();
}
}
if (this.transformedReference) {
return moment.tz(this.transformedReference, tz);
}
return null;
}
},
/**
* The type of the facet after the transformation has been applied
* @memberof! DatetimeTransform
*/
transformedType: {
deps: ['transformedFormat', 'transformedReference'],
fn: function () {
if (this.transformedReference) {
// datetime -> duration
return 'duration';
} else if (this.transformedFormat === 'ISO8601') {
// datetime -> datetime
return 'datetime';
} else {
// datetime -> time part
var timePart = util.timeParts.get(this.transformedFormat, 'description');
if (timePart && timePart.type) {
return timePart.type;
}
}
return 'datetime';
},
cache: false
},
/**
* The minium value this facet can take, after the transformation has been applied
* @type {number}
* @memberof! DatetimeTransform
*/
transformedMin: {
deps: ['transformedType'],
fn: function () {
var timePart;
if (this.transformedType === 'datetime' || this.transformedType === 'duration') {
return this.transform(this.parent.minval);
}
timePart = util.timeParts.get(this.transformedFormat, 'description');
if (timePart.calcualte) {
return this.transform(this.parent.minval);
} else {
return timePart.min;
}
},
cache: false
},
/**
* The maximum value this facet can take, after the transformation has been applied
* @type {number}
* @memberof! DatetimeTransform
*/
transformedMax: {
deps: ['transformedType'],
fn: function () {
var timePart;
if (this.transformedType === 'datetime' || this.transformedType === 'duration') {
return this.transform(this.parent.maxval);
}
timePart = util.timeParts.get(this.transformedFormat, 'description');
if (timePart.calcualte) {
return this.transform(this.parent.maxval);
} else {
return timePart.max;
}
},
cache: false
},
/**
* The minimum value this facet can take, after the transformation has been applied
*
* @type {string}
* @memberof! DatetimeTransform
*/
transformedMinAsText: {
deps: ['transformedMin', 'transformedType'],
fn: function () {
var minval = this.transformedMin;
if (this.transformedType === 'datetime') {
return minval.format();
} else {
return minval.toString();
}
},
cache: false
},
/**
* The maximum value this facet can take, after the transformation has been applied
*
* @type {string}
* @memberof! DatetimeTransform
*/
transformedMaxAsText: {
deps: ['transformedMax', 'transformedType'],
fn: function () {
var maxval = this.transformedMax;
if (this.transformedType === 'datetime') {
return maxval.format();
} else {
return maxval.toString();
}
},
cache: false
}
},
/**
* @function
* @memberof! DatetimeTransform
* @param {Object} momentjs
* @returns {Object} momentjs
*/
transform: function transform (inval) {
if (typeof inval === 'undefined') {
return misval;
}
var d = inval.clone();
var timePart;
if (this.referenceMoment) {
// datetime -> duration
return moment.duration(d.diff(this.referenceMoment, 'milliseconds', true), 'milliseconds');
} else if (this.transformedFormat !== 'ISO8601') {
timePart = util.timeParts.get(this.transformedFormat, 'description');
if (timePart && timePart.momentFormat) {
return d.format(timePart.momentFormat);
}
return d;
} else {
return d;
}
},
reset: function () {
this.unset(['zone', 'transformedFormat', 'transformedZone', 'transformedReference']);
}
});