time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

main.js (5219B)


      1 /**
      2 * @license Apache-2.0
      3 *
      4 * Copyright (c) 2021 The Stdlib Authors.
      5 *
      6 * Licensed under the Apache License, Version 2.0 (the "License");
      7 * you may not use this file except in compliance with the License.
      8 * You may obtain a copy of the License at
      9 *
     10 *    http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing, software
     13 * distributed under the License is distributed on an "AS IS" BASIS,
     14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 * See the License for the specific language governing permissions and
     16 * limitations under the License.
     17 */
     18 
     19 'use strict';
     20 
     21 // MODULES //
     22 
     23 var hasOwnProp = require( '@stdlib/assert/has-own-property' );
     24 var isInteger = require( '@stdlib/assert/is-integer' );
     25 var isString = require( '@stdlib/assert/is-string' ).isPrimitive;
     26 var isObject = require( '@stdlib/assert/is-object' );
     27 var floor = require( '@stdlib/math/base/special/floor' );
     28 var round = require( '@stdlib/math/base/special/round' );
     29 var ceil = require( '@stdlib/math/base/special/ceil' );
     30 
     31 
     32 // VARIABLES //
     33 
     34 var timestamp = /^\d{10}$|^\d{13}$/;
     35 var rounders = [ 'floor', 'ceil', 'round' ];
     36 
     37 
     38 // FUNCTIONS //
     39 
     40 /**
     41 * Validates a date parameter.
     42 *
     43 * @private
     44 * @param {*} value - value to be validated
     45 * @param {string} name - name to be used in error messages
     46 * @throws {TypeError} value must either be a date string, Date object, Unix timestamp, or JavaScript timestamp
     47 * @throws {Error} numeric date must be either a Unix or Javascript timestamp
     48 * @returns {Date} validated date
     49 */
     50 function validDate( value, name ) {
     51 	var type;
     52 
     53 	type = typeof value;
     54 	if ( type === 'string' ) {
     55 		value = Date.parse( value );
     56 		if ( value !== value ) {
     57 			throw new Error( 'invalid argument. Unable to parse ' + name.toLowerCase() + ' date.' );
     58 		}
     59 		value = new Date( value );
     60 	}
     61 	if ( type === 'number' ) {
     62 		if ( !timestamp.test( value ) ) {
     63 			throw new Error( 'invalid argument. Numeric ' + name.toLowerCase() + ' date must be either a Unix or Javascript timestamp.' );
     64 		}
     65 		if ( value.toString().length === 10 ) {
     66 			value *= 1000; // sec to ms
     67 		}
     68 		value = new Date( value );
     69 	}
     70 	if ( !(value instanceof Date) ) {
     71 		throw new TypeError( 'invalid argument. ' + name + ' date must either be a date string, Date object, Unix timestamp, or JavaScript timestamp.' );
     72 	}
     73 	return value;
     74 }
     75 
     76 
     77 // MAIN //
     78 
     79 /**
     80 * Generates an array of linearly spaced dates.
     81 *
     82 * @param {(Date|number|string)} start - start time as either a `Date` object, Unix timestamp, JavaScript timestamp, or date string
     83 * @param {(Date|number|string)} stop - stop time as either a `Date` object, Unix timestamp, JavaScript timestamp, or date string
     84 * @param {number} [length] - output array length (default: 100)
     85 * @param {Object} [options] - function options
     86 * @param {string} [options.round] - specifies how sub-millisecond times should be rounded: [ 'floor', 'ceil', 'round' ] (default: 'floor' )
     87 * @throws {TypeError} length argument must a positive integer
     88 * @throws {Error} must provide valid options
     89 * @returns {Array} array of dates
     90 *
     91 * @example
     92 * var stop = '2014-12-02T07:00:54.973Z';
     93 * var start = new Date( stop ) - 60000;
     94 *
     95 * var arr = datespace( start, stop, 6 );
     96 * // returns [...]
     97 *
     98 * @example
     99 * // Equivalent of Math.ceil():
    100 * var arr = datespace( 1417503655000, 1417503655001, 3, { 'round': 'ceil' } );
    101 * // returns [...]
    102 *
    103 * // Equivalent of Math.round():
    104 * arr = datespace( 1417503655000, 1417503655001, 3, { 'round': 'round' } );
    105 * // returns [...]
    106 */
    107 function datespace( start, stop, length, options ) {
    108 	var opts;
    109 	var len;
    110 	var flg;
    111 	var arr;
    112 	var end;
    113 	var fcn;
    114 	var tmp;
    115 	var d;
    116 	var i;
    117 
    118 	len = 100;
    119 	flg = true;
    120 	opts = {
    121 		'round': 'floor'
    122 	};
    123 	start = validDate( start, 'Start' );
    124 	stop = validDate( stop, 'Stop' );
    125 	if ( arguments.length > 2 ) {
    126 		if ( arguments.length === 3 ) {
    127 			if ( isObject( length ) ) {
    128 				opts = length;
    129 			} else {
    130 				len = length;
    131 
    132 				// Turn off checking the options object...
    133 				flg = false;
    134 			}
    135 		} else {
    136 			opts = options;
    137 			len = length;
    138 		}
    139 		if ( len === 0 ) {
    140 			return [];
    141 		}
    142 		if ( !isInteger( len ) || len < 0 ) {
    143 			throw new TypeError( 'invalid argument. Length must a positive integer.' );
    144 		}
    145 		if ( flg ) {
    146 			if ( !isObject( opts ) ) {
    147 				throw new TypeError( 'invalid argument. Options argument must be an object. Value: `' + opts + '`.' );
    148 			}
    149 			if ( hasOwnProp( opts, 'round' ) ) {
    150 				if ( !isString( opts.round ) ) {
    151 					throw new TypeError( 'invalid option. `round` option must be a string.' );
    152 				}
    153 				if ( rounders.indexOf( opts.round ) === -1 ) {
    154 					throw new Error( 'invalid input option. `round` option must be one of [' + rounders.join( ',' ) + '].' );
    155 				}
    156 			}
    157 		}
    158 	}
    159 	switch ( opts.round ) {
    160 	case 'round':
    161 		fcn = round;
    162 		break;
    163 	case 'ceil':
    164 		fcn = ceil;
    165 		break;
    166 	default:
    167 	case 'floor':
    168 		fcn = floor;
    169 		break;
    170 	}
    171 
    172 	// Calculate the increment...
    173 	end = len - 1;
    174 	d = ( stop.getTime() - start.getTime() ) / end;
    175 
    176 	// Build the output array...
    177 	arr = new Array( len );
    178 	tmp = start;
    179 	arr[ 0 ] = tmp;
    180 	tmp = tmp.getTime();
    181 	for ( i = 1; i < end; i++ ) {
    182 		tmp += d;
    183 		arr[ i ] = new Date( fcn( tmp ) );
    184 	}
    185 	arr[ end ] = stop;
    186 	return arr;
    187 }
    188 
    189 
    190 // EXPORTS //
    191 
    192 module.exports = datespace;