/**
* JTSage-DateBox
* @fileOverview Widget binder. Used only in the test enviroment.
* @author J.T.Sage <jtsage+datebox@gmail.com>
* @author {@link https://github.com/jtsage/jtsage-datebox/contributors|GitHub Contributors}
* @license {@link https://github.com/jtsage/jtsage-datebox/blob/master/LICENSE.txt|MIT}
* @version 5.2.0
*/
/**
* Enhance the date object for easier use.
*
* These are direct extensions to the JavaScript date object
*
* All methods are also chainable, which is not true of some implementations
* in a browser.
*
* @memberOf JTSageDateBox
* @namespace JTSageDateBox._enhanceDate
*/
JTSageDateBox._enhanceDate = function() {
Object.assign(this._date.prototype, {
/**
* Return a copy of the date, not altering the original
*
* You may specify partial arrays only as deep as the most
* precise element you want to adjust or override. Zeros will
* not alter that element. Overrides takes precedence over adjustments
*
* @param {array} adjust [y,m,d,h,i,s,ms] Adjust part of the date
* @param {array} override [y,m,d,h,i,s,ms] Override part of the date
* @return {object} JavaScript date object
* @memberOf JTSageDateBox._enhanceDate
*/
copy : function( adjust, override ) {
adjust = Object.assign( [0,0,0,0,0,0,0], adjust );
override = Object.assign( [0,0,0,0,0,0,0], override );
return new Date(
( ( override[ 0 ] > 0 ) ? override[ 0 ] : this.get( 0 ) + adjust[ 0 ] ),
( ( override[ 1 ] > 0 ) ? override[ 1 ] : this.get( 1 ) + adjust[ 1 ] ),
( ( override[ 2 ] > 0 ) ? override[ 2 ] : this.get( 2 ) + adjust[ 2 ] ),
( ( override[ 3 ] > 0 ) ? override[ 3 ] : this.get( 3 ) + adjust[ 3 ] ),
( ( override[ 4 ] > 0 ) ? override[ 4 ] : this.get( 4 ) + adjust[ 4 ] ),
( ( override[ 5 ] > 0 ) ? override[ 5 ] : this.get( 5 ) + adjust[ 5 ] ),
( ( override[ 6 ] > 0 ) ? override[ 5 ] : this.get( 6 ) + adjust[ 6 ] ));
},
/**
* Adjust the date by a relative amount.
* @param {number} type Element to shift, 0 = year, 5 = seconds
* @param {number} amount Offset amount, positive or negative
* @return {object} JavaScript date object
* @memberOf JTSageDateBox._enhanceDate
*/
adj : function (type, amount) {
// Adjust the date. Yes, this is chainable
if ( typeof amount !== "number" || typeof type !== "number" ) {
throw new Error( "Invalid Arguments" );
}
switch ( type ) {
case 0 : this.setD( 0, this.get( 0 ) + amount ); break;
case 1 : this.setD( 1, this.get( 1 ) + amount ); break;
case 2 : this.setD( 2, this.get( 2 ) + amount ); break;
case 3 : amount *= 60;
/* falls through */
case 4 : amount *= 60;
/* falls through */
case 5 : amount *= 1000;
/* falls through */
case 6 : this.setTime( this.getTime() + amount ); break;
}
return this;
},
/**
* Set part of the date, chainable
*
* @param {number} type Element to set, 0 = year, 5 = seconds
* @param {number} amount Value to set
* @return {object} JavaScript date object
* @memberOf JTSageDateBox._enhanceDate
*/
setD : function(type, amount) {
// A chainable version of setWhatever()
switch ( type ) {
case 0 : this.setFullYear( amount ); break;
case 1 : this.setMonth( amount ); break;
case 2 : this.setDate( amount ); break;
case 3 : this.setHours( amount ); break;
case 4 : this.setMinutes( amount ); break;
case 5 : this.setSeconds( amount ); break;
case 6 : this.setMilliseconds( amount ); break;
}
return this;
},
/**
* Get part of the date
*
* @param {number} type Element to set, 0 = year, 5 = seconds
* @return {number} Date part
* @memberOf JTSageDateBox._enhanceDate
*/
get : function(type) {
// Chainable version of get. Also shorter.
switch ( type ) {
case 0 : return this.getFullYear();
case 1 : return this.getMonth();
case 2 : return this.getDate();
case 3 : return this.getHours();
case 4 : return this.getMinutes();
case 5 : return this.getSeconds();
case 6 : return this.getMilliseconds();
}
return false;
},
/**
* Get the hour in 12 hour format - midnight = 12, 13:00 = 1
* @return {number} Hour
* @memberOf JTSageDateBox._enhanceDate
*/
get12hr : function() {
if ( this.get( 3 ) === 0 ) { return 12; }
if ( this.get( 3 ) < 13 ) { return this.get( 3 ); }
return this.get( 3 ) - 12;
},
/**
* Get an ISO-8601 version of the date : YYYY-MM-DD
*
* @return {string} ISO-8601 String
* @memberOf JTSageDateBox._enhanceDate
*/
iso : function() {
var arr = [0,0,0], i = 0;
for ( i=0; i < 3; i++ ) {
arr[ i ] = this.get( i );
if ( i === 1 ) { arr[ i ]++; }
if ( arr[i] < 10 ) { arr[ i ] = "0" + String( arr[ i ] ); }
}
return arr.join( "-" );
},
/**
* Retrieve a numericly comparable representation of the date : YYYYMMDD
*
* @return {number} Date as an integer
* @memberOf JTSageDateBox._enhanceDate
*/
comp : function () {
return parseInt( this.iso().replace( /-/g, "" ), 10 );
},
/**
* Get the number of seconds since epoch
*
* @return {number} Seconds
* @memberOf JTSageDateBox._enhanceDate
*/
getEpoch : function() {
return Math.floor( this.getTime() / 1000 );
},
/**
* Get the number of days since epoch
*
* @return {number} Days
* @memberOf JTSageDateBox._enhanceDate
*/
getEpochDays : function() {
return Math.floor( this.getTime() / ( 1000*60*60*24 ) );
},
/**
* Get the date as an array
*
* @return {array} [y,m,d,h,i,s]
* @memberOf JTSageDateBox._enhanceDate
*/
getArray : function() {
var arr = [ 0, 0, 0, 0, 0, 0 ], i = 0;
for ( i = 0; i < 6; i++ ) {
arr[i] = this.get( i );
}
return arr;
},
/**
* Set date to the first valid day of the current month.
*
* @param {number} day Day of week. Zero based
* @return {object} JavaScript date object
* @memberOf JTSageDateBox._enhanceDate
*/
setFirstDay : function (day) {
// Grabs first valid (day) of current month
this.setD( 2, 1 ).adj( 2, ( day - this.getDay() ) );
if ( this.get( 2 ) > 10 ) { this.adj( 2, 7 ); }
return this;
},
/**
* Set the week number.
*
* Types :
* - 0 : Sunday Based
* - 1 : Monday Based
* - 4 : Thursday Based (ISO-8601 standard)
*
* @param {number} type Type of week calculation. Day of week probably
* @param {number} number Week number
* @return {object} JavaScript date object
* @memberOf JTSageDateBox._enhanceDate
*/
setDWeek : function (type,num) {
if ( type === 4 ) {
return this.setD(1,0).setD(2,1).setFirstDay(4).adj(2,-3).adj(2,(num-1)*7);
}
return this.setD(1,0).setD(2,1).setFirstDay(type).adj(2,(num-1)*7);
},
/**
* Get the week number.
*
* Types :
* - 0 : Sunday Based
* - 1 : Monday Based
* - 4 : Thursday Based (ISO-8601 standard)
*
* @param {number} type Type of calculation
* @return {number} Week number
* @memberOf JTSageDateBox._enhanceDate
*/
getDWeek : function (type) {
var t1, t2;
switch ( type ) {
case 0:
t1 = this.copy([0,-1*this.getMonth()]).setFirstDay(0);
return Math.floor(
( this.getTime() - ( t1.getTime() + (
( this.getTimezoneOffset() - t1.getTimezoneOffset() ) * 60000
))) / 6048e5 ) + 1;
case 1:
t1 = this.copy([0,-1*this.getMonth()]).setFirstDay(1);
return Math.floor(
( this.getTime() - ( t1.getTime() + (
( this.getTimezoneOffset() - t1.getTimezoneOffset() ) * 60000
))) / 6048e5 ) + 1;
case 4:
// this line is some bullshit. but it does work.
// (trap for dec 29, 30, or 31st being in the new year's week - these
// are the only 3 that can possibly fall like this)
if ( this.getMonth() === 11 && this.getDate() > 28 ) { return 1; }
t1 = this.copy([0,-1*this.getMonth()],true).setFirstDay(4).adj(2,-3);
t2 = Math.floor(
( this.getTime() - ( t1.getTime() + (
( this.getTimezoneOffset() - t1.getTimezoneOffset() ) * 60000
))) / 6048e5 ) + 1;
if ( t2 < 1 ) {
t1 = this.copy([-1,-1*this.getMonth()]).setFirstDay(4).adj(2,-3);
return Math.floor((this.getTime() - t1.getTime()) / 6048e5) + 1;
}
return t2;
default:
return 0;
}
}
});
};