@ -29,10 +29,12 @@ var util = require('../util');
* @ param { Number } [ minimumStep ] Optional . Minimum step size in milliseconds
* /
function TimeStep ( start , end , minimumStep , hiddenDates ) {
this . moment = moment ;
// variables
this . current = new Date ( ) ;
this . _start = new Date ( ) ;
this . _end = new Date ( ) ;
this . current = this . moment ( ) ;
this . _start = this . moment ( ) ;
this . _end = this . moment ( ) ;
this . autoScale = true ;
this . scale = 'day' ;
@ -77,6 +79,20 @@ TimeStep.FORMAT = {
}
} ;
/ * *
* Set custom constructor function for moment . Can be used to set dates
* to UTC or to set a utcOffset .
* @ param { function } moment
* /
TimeStep . prototype . setMoment = function ( moment ) {
this . moment = moment ;
// update the date properties, can have a new utcOffset
this . current = this . moment ( this . current ) ;
this . _start = this . moment ( this . _start ) ;
this . _end = this . moment ( this . _end ) ;
} ;
/ * *
* Set custom formatting for the minor an major labels of the TimeStep .
* Both ` minorLabels ` and ` majorLabels ` are an Object with properties :
@ -103,8 +119,8 @@ TimeStep.prototype.setRange = function(start, end, minimumStep) {
throw "No legal start or end date in method setRange" ;
}
this . _start = ( start != undefined ) ? new Date ( start . valueOf ( ) ) : new Date ( ) ;
this . _end = ( end != undefined ) ? new Date ( end . valueOf ( ) ) : new Date ( ) ;
this . _start = ( start != undefined ) ? this . moment ( start . valueOf ( ) ) : new Date ( ) ;
this . _end = ( end != undefined ) ? this . moment ( end . valueOf ( ) ) : new Date ( ) ;
if ( this . autoScale ) {
this . setMinimumStep ( minimumStep ) ;
@ -114,8 +130,8 @@ TimeStep.prototype.setRange = function(start, end, minimumStep) {
/ * *
* Set the range iterator to the start date .
* /
TimeStep . prototype . fir st = function ( ) {
this . current = new Date ( this . _start . valueOf ( ) ) ;
TimeStep . prototype . star t = function ( ) {
this . current = this . _start . clone ( ) ;
this . roundToMinor ( ) ;
} ;
@ -129,28 +145,28 @@ TimeStep.prototype.roundToMinor = function() {
// noinspection FallThroughInSwitchStatementJS
switch ( this . scale ) {
case 'year' :
this . current . setFullY ear( this . step * Math . floor ( this . current . getFullY ear( ) / this . step ) ) ;
this . current . setM onth( 0 ) ;
case 'month' : this . current . setD ate( 1 ) ;
this . current . y ear( this . step * Math . floor ( this . current . y ear( ) / this . step ) ) ;
this . current . m onth( 0 ) ;
case 'month' : this . current . d ate( 1 ) ;
case 'day' : // intentional fall through
case 'weekday' : this . current . setH ours( 0 ) ;
case 'hour' : this . current . setM inutes( 0 ) ;
case 'minute' : this . current . setSe conds ( 0 ) ;
case 'second' : this . current . setM illiseconds( 0 ) ;
case 'weekday' : this . current . h ours( 0 ) ;
case 'hour' : this . current . m inutes( 0 ) ;
case 'minute' : this . current . seconds ( 0 ) ;
case 'second' : this . current . m illiseconds( 0 ) ;
//case 'millisecond': // nothing to do for milliseconds
}
if ( this . step != 1 ) {
// round down to the first minor value that is a multiple of the current step size
switch ( this . scale ) {
case 'millisecond' : this . current . setMilliseconds ( this . current . getMilliseconds ( ) - this . current . getMilliseconds ( ) % this . step ) ; break ;
case 'second' : this . current . setSeconds ( this . current . getSeconds ( ) - this . current . getSeconds ( ) % this . step ) ; break ;
case 'minute' : this . current . setMinutes ( this . current . getMinutes ( ) - this . current . getMinutes ( ) % this . step ) ; break ;
case 'hour' : this . current . setHours ( this . current . getHours ( ) - this . current . getHours ( ) % this . step ) ; break ;
case 'millisecond' : this . current . subtract ( this . current . milliseconds ( ) % this . step , 'milliseconds' ) ; break ;
case 'second' : this . current . subtract ( this . current . seconds ( ) % this . step , 'seconds' ) ; break ;
case 'minute' : this . current . subtract ( this . current . minutes ( ) % this . step , 'minutes' ) ; break ;
case 'hour' : this . current . subtract ( this . current . hours ( ) % this . step , 'hours' ) ; break ;
case 'weekday' : // intentional fall through
case 'day' : this . current . setDate ( ( this . current . getD ate( ) - 1 ) - ( this . current . getDate ( ) - 1 ) % this . step + 1 ) ; break ;
case 'month' : this . current . setMonth ( this . current . getMonth ( ) - this . current . getM onth( ) % this . step ) ; break ;
case 'year' : this . current . setFullYear ( this . current . getFullYear ( ) - this . current . getFullY ear( ) % this . step ) ; break ;
case 'day' : this . current . subtract ( ( this . current . d ate( ) - 1 ) % this . step ) ; break ;
case 'month' : this . current . subtract ( this . current . m onth( ) % this . step ) ; break ;
case 'year' : this . current . subtract ( this . current . y ear( ) % this . step ) ; break ;
default : break ;
}
}
@ -172,67 +188,65 @@ TimeStep.prototype.next = function() {
// Two cases, needed to prevent issues with switching daylight savings
// (end of March and end of October)
if ( this . current . getM onth( ) < 6 ) {
if ( this . current . m onth( ) < 6 ) {
switch ( this . scale ) {
case 'millisecond' :
this . current = new Date ( this . current . valueOf ( ) + this . step ) ; break ;
case 'second' : this . current = new Date ( this . current . valueOf ( ) + this . step * 1000 ) ; break ;
case 'minute' : this . current = new Date ( this . current . valueOf ( ) + this . step * 1000 * 60 ) ; break ;
case 'millisecond' : this . current . add ( this . step , 'millisecond' ) ; break ;
case 'second' : this . current . add ( this . step , 'second' ) ; break ;
case 'minute' : this . current . add ( this . step , 'minute' ) ; break ;
case 'hour' :
this . current = new Date ( this . current . valueOf ( ) + this . step * 1000 * 60 * 60 ) ;
this . current . add ( this . step , 'hour' ) ;
// in case of skipping an hour for daylight savings, adjust the hour again (else you get: 0h 5h 9h ... instead of 0h 4h 8h ...)
var h = this . current . getHours ( ) ;
this . current . setHours ( h - ( h % this . step ) ) ;
// TODO: is this still needed now we use the function of moment.js?
this . current . subtract ( this . current . hours ( ) % this . step ) ;
break ;
case 'weekday' : // intentional fall through
case 'day' : this . current . setDate ( this . current . getDate ( ) + this . step ) ; break ;
case 'month' : this . current . setMonth ( this . current . getMonth ( ) + this . step ) ; break ;
case 'year' : this . current . setFullYear ( this . current . getFullYear ( ) + this . step ) ; break ;
default : break ;
case 'day' : this . current . add ( this . step , 'day' ) ; break ;
case 'month' : this . current . add ( this . step , 'month' ) ; break ;
case 'year' : this . current . add ( this . step , 'year' ) ; break ;
default : break ;
}
}
else {
switch ( this . scale ) {
case 'millisecond' : this . current = new Date ( this . current . valueOf ( ) + this . step ) ; break ;
case 'second' : this . current . setSeconds ( this . current . getSeconds ( ) + this . step ) ; break ;
case 'minute' : this . current . setMinutes ( this . current . getMinutes ( ) + this . step ) ; break ;
case 'hour' : this . current . setHours ( this . current . getHours ( ) + this . step ) ; break ;
case 'millisecond' : this . current . add ( this . step , 'millisecond' ) ; break ;
case 'second' : this . current . add ( this . step , 'second' ) ; break ;
case 'minute' : this . current . add ( this . step , 'minute' ) ; break ;
case 'hour' : this . current . add ( this . step , 'hour' ) ; break ;
case 'weekday' : // intentional fall through
case 'day' : this . current . setDate ( this . current . getDate ( ) + this . step ) ; break ;
case 'month' : this . current . setMonth ( this . current . getMonth ( ) + this . step ) ; break ;
case 'year' : this . current . setFullYear ( this . current . getFullYear ( ) + this . step ) ; break ;
default : break ;
case 'day' : this . current . add ( this . step , 'day' ) ; break ;
case 'month' : this . current . add ( this . step , 'month' ) ; break ;
case 'year' : this . current . add ( this . step , 'year' ) ; break ;
default : break ;
}
}
if ( this . step != 1 ) {
// round down to the correct major value
switch ( this . scale ) {
case 'millisecond' : if ( this . current . getM illiseconds( ) < this . step ) this . current . setM illiseconds( 0 ) ; break ;
case 'second' : if ( this . current . getS econds( ) < this . step ) this . current . setS econds ( 0 ) ; break ;
case 'minute' : if ( this . current . getM inutes( ) < this . step ) this . current . setM inutes( 0 ) ; break ;
case 'hour' : if ( this . current . getH ours( ) < this . step ) this . current . setH ours( 0 ) ; break ;
case 'millisecond' : if ( this . current . m illiseconds( ) < this . step ) this . current . m illiseconds( 0 ) ; break ;
case 'second' : if ( this . current . s econds( ) < this . step ) this . current . seconds ( 0 ) ; break ;
case 'minute' : if ( this . current . m inutes( ) < this . step ) this . current . m inutes( 0 ) ; break ;
case 'hour' : if ( this . current . h ours( ) < this . step ) this . current . h ours( 0 ) ; break ;
case 'weekday' : // intentional fall through
case 'day' : if ( this . current . getD ate( ) < this . step + 1 ) this . current . setD ate( 1 ) ; break ;
case 'month' : if ( this . current . getM onth( ) < this . step ) this . current . setM onth( 0 ) ; break ;
case 'day' : if ( this . current . d ate( ) < this . step + 1 ) this . current . d ate( 1 ) ; break ;
case 'month' : if ( this . current . m onth( ) < this . step ) this . current . m onth( 0 ) ; break ;
case 'year' : break ; // nothing to do for year
default : break ;
default : break ;
}
}
// safety mechanism: if current time is still unchanged, move to the end
if ( this . current . valueOf ( ) == prev ) {
this . current = new Date ( this . _end . valueOf ( ) ) ;
this . current = this . _end . clone ( ) ;
}
DateUtil . stepOverHiddenDates ( this , prev ) ;
DateUtil . stepOverHiddenDates ( this . moment , this , prev ) ;
} ;
/ * *
* Get the current datetime
* @ return { Date } current The current date
* @ return { Moment } current The current date
* /
TimeStep . prototype . getCurrent = function ( ) {
return this . current ;
@ -329,100 +343,100 @@ TimeStep.prototype.setMinimumStep = function(minimumStep) {
* @ return { Date } snappedDate
* /
TimeStep . snap = function ( date , scale , step ) {
var clone = new Date ( date . valueOf ( ) ) ;
var clone = moment ( date ) ;
if ( scale == 'year' ) {
var year = clone . getFullY ear( ) + Math . round ( clone . getM onth( ) / 12 ) ;
clone . setFullY ear( Math . round ( year / step ) * step ) ;
clone . setM onth( 0 ) ;
clone . setD ate( 0 ) ;
clone . setH ours( 0 ) ;
clone . setM inutes( 0 ) ;
clone . setSe conds ( 0 ) ;
clone . setMi lliseconds( 0 ) ;
var year = clone . y ear( ) + Math . round ( clone . m onth( ) / 12 ) ;
clone . y ear( Math . round ( year / step ) * step ) ;
clone . m onth( 0 ) ;
clone . d ate( 0 ) ;
clone . h ours( 0 ) ;
clone . m inutes( 0 ) ;
clone . seconds ( 0 ) ;
clone . m lliseconds( 0 ) ;
}
else if ( scale == 'month' ) {
if ( clone . getD ate( ) > 15 ) {
clone . setD ate( 1 ) ;
clone . setMonth ( clone . getMonth ( ) + 1 ) ;
if ( clone . d ate( ) > 15 ) {
clone . d ate( 1 ) ;
clone . add ( 1 , 'month' ) ;
// important: first set Date to 1, after that change the month.
}
else {
clone . setD ate( 1 ) ;
clone . d ate( 1 ) ;
}
clone . setH ours( 0 ) ;
clone . setM inutes( 0 ) ;
clone . setSe conds ( 0 ) ;
clone . setM illiseconds( 0 ) ;
clone . h ours( 0 ) ;
clone . m inutes( 0 ) ;
clone . seconds ( 0 ) ;
clone . m illiseconds( 0 ) ;
}
else if ( scale == 'day' ) {
//noinspection FallthroughInSwitchStatementJS
switch ( step ) {
case 5 :
case 2 :
clone . setH ours( Math . round ( clone . getH ours( ) / 24 ) * 24 ) ; break ;
clone . h ours( Math . round ( clone . h ours( ) / 24 ) * 24 ) ; break ;
default :
clone . setH ours( Math . round ( clone . getH ours( ) / 12 ) * 12 ) ; break ;
clone . h ours( Math . round ( clone . h ours( ) / 12 ) * 12 ) ; break ;
}
clone . setM inutes( 0 ) ;
clone . setSe conds ( 0 ) ;
clone . setM illiseconds( 0 ) ;
clone . m inutes( 0 ) ;
clone . seconds ( 0 ) ;
clone . m illiseconds( 0 ) ;
}
else if ( scale == 'weekday' ) {
//noinspection FallthroughInSwitchStatementJS
switch ( step ) {
case 5 :
case 2 :
clone . setH ours( Math . round ( clone . getH ours( ) / 12 ) * 12 ) ; break ;
clone . h ours( Math . round ( clone . h ours( ) / 12 ) * 12 ) ; break ;
default :
clone . setH ours( Math . round ( clone . getH ours( ) / 6 ) * 6 ) ; break ;
clone . h ours( Math . round ( clone . h ours( ) / 6 ) * 6 ) ; break ;
}
clone . setM inutes( 0 ) ;
clone . setSe conds ( 0 ) ;
clone . setM illiseconds( 0 ) ;
clone . m inutes( 0 ) ;
clone . seconds ( 0 ) ;
clone . m illiseconds( 0 ) ;
}
else if ( scale == 'hour' ) {
switch ( step ) {
case 4 :
clone . setM inutes( Math . round ( clone . getM inutes( ) / 60 ) * 60 ) ; break ;
clone . m inutes( Math . round ( clone . m inutes( ) / 60 ) * 60 ) ; break ;
default :
clone . setM inutes( Math . round ( clone . getM inutes( ) / 30 ) * 30 ) ; break ;
clone . m inutes( Math . round ( clone . m inutes( ) / 30 ) * 30 ) ; break ;
}
clone . setSe conds ( 0 ) ;
clone . setM illiseconds( 0 ) ;
clone . seconds ( 0 ) ;
clone . m illiseconds( 0 ) ;
} else if ( scale == 'minute' ) {
//noinspection FallthroughInSwitchStatementJS
switch ( step ) {
case 15 :
case 10 :
clone . setM inutes( Math . round ( clone . getM inutes( ) / 5 ) * 5 ) ;
clone . setSe conds ( 0 ) ;
clone . m inutes( Math . round ( clone . m inutes( ) / 5 ) * 5 ) ;
clone . seconds ( 0 ) ;
break ;
case 5 :
clone . setSe conds ( Math . round ( clone . getS econds( ) / 60 ) * 60 ) ; break ;
clone . seconds ( Math . round ( clone . s econds( ) / 60 ) * 60 ) ; break ;
default :
clone . setSe conds ( Math . round ( clone . getS econds( ) / 30 ) * 30 ) ; break ;
clone . seconds ( Math . round ( clone . s econds( ) / 30 ) * 30 ) ; break ;
}
clone . setM illiseconds( 0 ) ;
clone . m illiseconds( 0 ) ;
}
else if ( scale == 'second' ) {
//noinspection FallthroughInSwitchStatementJS
switch ( step ) {
case 15 :
case 10 :
clone . setSe conds ( Math . round ( clone . getS econds( ) / 5 ) * 5 ) ;
clone . setM illiseconds( 0 ) ;
clone . seconds ( Math . round ( clone . s econds( ) / 5 ) * 5 ) ;
clone . m illiseconds( 0 ) ;
break ;
case 5 :
clone . setM illiseconds( Math . round ( clone . getM illiseconds( ) / 1000 ) * 1000 ) ; break ;
clone . m illiseconds( Math . round ( clone . m illiseconds( ) / 1000 ) * 1000 ) ; break ;
default :
clone . setM illiseconds( Math . round ( clone . getM illiseconds( ) / 500 ) * 500 ) ; break ;
clone . m illiseconds( Math . round ( clone . m illiseconds( ) / 500 ) * 500 ) ; break ;
}
}
else if ( scale == 'millisecond' ) {
var _step = step > 5 ? step / 2 : 1 ;
clone . setM illiseconds( Math . round ( clone . getM illiseconds( ) / _step ) * _step ) ;
clone . m illiseconds( Math . round ( clone . m illiseconds( ) / _step ) * _step ) ;
}
return clone ;
@ -477,20 +491,21 @@ TimeStep.prototype.isMajor = function() {
}
}
var date = this . moment ( this . current ) ;
switch ( this . scale ) {
case 'millisecond' :
return ( this . current . getM illiseconds( ) == 0 ) ;
return ( date . m illiseconds( ) == 0 ) ;
case 'second' :
return ( this . current . getS econds( ) == 0 ) ;
return ( date . s econds( ) == 0 ) ;
case 'minute' :
return ( this . current . getH ours( ) == 0 ) && ( this . current . getM inutes( ) == 0 ) ;
return ( date . h ours( ) == 0 ) && ( date . m inutes( ) == 0 ) ;
case 'hour' :
return ( this . current . getH ours( ) == 0 ) ;
return ( date . h ours( ) == 0 ) ;
case 'weekday' : // intentional fall through
case 'day' :
return ( this . current . getD ate( ) == 1 ) ;
return ( date . d ate( ) == 1 ) ;
case 'month' :
return ( this . current . getM onth( ) == 0 ) ;
return ( date . m onth( ) == 0 ) ;
case 'year' :
return false ;
default :
@ -511,7 +526,7 @@ TimeStep.prototype.getLabelMinor = function(date) {
}
var format = this . format . minorLabels [ this . scale ] ;
return ( format && format . length > 0 ) ? moment ( date ) . format ( format ) : '' ;
return ( format && format . length > 0 ) ? this . moment ( date ) . format ( format ) : '' ;
} ;
/ * *
@ -526,12 +541,13 @@ TimeStep.prototype.getLabelMajor = function(date) {
}
var format = this . format . majorLabels [ this . scale ] ;
return ( format && format . length > 0 ) ? moment ( date ) . format ( format ) : '' ;
return ( format && format . length > 0 ) ? this . moment ( date ) . format ( format ) : '' ;
} ;
TimeStep . prototype . getClassName = function ( ) {
var m = moment ( this . current ) ;
var date = m . locale ? m . locale ( 'en' ) : m . lang ( 'en' ) ; // old versions of moment have .lang() function
var _moment = this . moment ;
var m = this . moment ( this . current ) ;
var current = m . locale ? m . locale ( 'en' ) : m . lang ( 'en' ) ; // old versions of moment have .lang() function
var step = this . step ;
function even ( value ) {
@ -542,10 +558,10 @@ TimeStep.prototype.getClassName = function() {
if ( date . isSame ( new Date ( ) , 'day' ) ) {
return ' vis-today' ;
}
if ( date . isSame ( moment ( ) . add ( 1 , 'day' ) , 'day' ) ) {
if ( date . isSame ( _ moment( ) . add ( 1 , 'day' ) , 'day' ) ) {
return ' vis-tomorrow' ;
}
if ( date . isSame ( moment ( ) . add ( - 1 , 'day' ) , 'day' ) ) {
if ( date . isSame ( _ moment( ) . add ( - 1 , 'day' ) , 'day' ) ) {
return ' vis-yesterday' ;
}
return '' ;
@ -565,37 +581,37 @@ TimeStep.prototype.getClassName = function() {
switch ( this . scale ) {
case 'millisecond' :
return even ( date . milliseconds ( ) ) . trim ( ) ;
return even ( current . milliseconds ( ) ) . trim ( ) ;
case 'second' :
return even ( date . seconds ( ) ) . trim ( ) ;
return even ( current . seconds ( ) ) . trim ( ) ;
case 'minute' :
return even ( date . minutes ( ) ) . trim ( ) ;
return even ( current . minutes ( ) ) . trim ( ) ;
case 'hour' :
var hours = date . hours ( ) ;
var hours = current . hours ( ) ;
if ( this . step == 4 ) {
hours = hours + '-h' + ( hours + 4 ) ;
}
return 'vis-h' + hours + today ( date ) + even ( date . hours ( ) ) ;
return 'vis-h' + hours + today ( current ) + even ( current . hours ( ) ) ;
case 'weekday' :
return 'vis-' + date . format ( 'dddd' ) . toLowerCase ( ) +
today ( date ) + currentWeek ( date ) + even ( date . date ( ) ) ;
return 'vis-' + current . format ( 'dddd' ) . toLowerCase ( ) +
today ( current ) + currentWeek ( current ) + even ( current . date ( ) ) ;
case 'day' :
var day = date . date ( ) ;
var month = date . format ( 'MMMM' ) . toLowerCase ( ) ;
return 'vis-day' + day + ' vis-' + month + currentMonth ( date ) + even ( day - 1 ) ;
var day = current . date ( ) ;
var month = current . format ( 'MMMM' ) . toLowerCase ( ) ;
return 'vis-day' + day + ' vis-' + month + currentMonth ( current ) + even ( day - 1 ) ;
case 'month' :
return 'vis-' + date . format ( 'MMMM' ) . toLowerCase ( ) +
currentMonth ( date ) + even ( date . month ( ) ) ;
return 'vis-' + current . format ( 'MMMM' ) . toLowerCase ( ) +
currentMonth ( current ) + even ( current . month ( ) ) ;
case 'year' :
var year = date . year ( ) ;
return 'vis-year' + year + currentYear ( date ) + even ( year ) ;
var year = current . year ( ) ;
return 'vis-year' + year + currentYear ( current ) + even ( year ) ;
default :
return '' ;