All files index.js

100% Statements 63/63
100% Branches 28/28
100% Functions 9/9
100% Lines 63/63
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 1161x   1x 1x 1x 1x 1x 1x     6x 6x 2x   4x 4x       9x 9x     9x       8x 8x           2x 2x 1x 1x         7x 1x   6x 6x 6x 3x 3x 3x   6x 6x 2x   4x 1x 1x 1x   4x 4x 2x   4x       8x 2x   6x 6x 2x   4x 4x 2x   4x         4x 1x 1x   3x 1x   2x   3x   4x 4x 3x   4x       1x   1x     1x            
const nano = require('nano-seconds');
 
const SECONDS_TO_EPOCH = 62135596800;
const MS_PER_SEC = 1000;
const NS_PER_TICK = 100;
const TICKS_PER_MS = 10000;
const MAX_TS = 253402300799999;
const MIN_TS = -62135596800000;
 
function toString() {
  const us = `${this[1]}`;
  if (this[0] === 0) {
    return us;
  }
  const pad = '0000000'.substring(0, 7 - us.length);
  return `${this[0]}${pad}${us}`;
}
 
function toTickObj([secs, ticks]) {
  const tarr = [secs, ticks];
  Object.defineProperty(tarr, 'toString', {
    value: toString
  });
  return Object.freeze(tarr);
}
 
function tsToArray(ts) {
  const tickTs = ts + (SECONDS_TO_EPOCH * MS_PER_SEC);
  return [Math.trunc(tickTs / MS_PER_SEC), ~~(tickTs % MS_PER_SEC) * TICKS_PER_MS];
}
 
 
 
function rollOver(tickArr, overflow) {
  tickArr[1] += overflow;
  if (tickArr[1] < 0) {
    tickArr[1] += (TICKS_PER_MS * MS_PER_SEC);
    tickArr[0] -= 1;
  }
}
 
function at(...args) {
  if (args.length < 2) {
    throw new Error('This function needs to be called with at least two numbers.');
  }
  let ms = 0;
  let overflow = 0;
  if (args.length >= 7) {
    ms = Math.trunc(args[6] / TICKS_PER_MS);
    overflow = args[6] % TICKS_PER_MS;
    args[6] = ms;
  }
  let point = Date.UTC(...args);
  if (point < MIN_TS || point > MAX_TS) {
    throw new Error('This date is out of range of standard .NET DateTime(Offset)');
  }
  if (args[0] < 100) {
    const pdate = new Date(point);
    pdate.setUTCFullYear(args[0]);
    point = pdate.getTime();
  }
  const arr = tsToArray(point);
  if (overflow !== 0) {
    rollOver(arr, overflow);
  }
  return toTickObj(arr);
}
 
function from(dtObj) {
  if (Object.prototype.toString.call(dtObj) !== '[object Date]') {
    throw new Error('Argument is not a date object');
  }
  const point = dtObj.getTime();
  if (point < MIN_TS || point > MAX_TS) {
    throw new Error('This date is out of range of standard .NET DateTime(Offset)');
  }
  const arr = tsToArray(point);
  if (dtObj.getTicks) {
    arr[1] += dtObj.getTicks();
  }
  return toTickObj(arr);
}
 
function to(ticks) {
  let ts, extra;
  if (Array.isArray(ticks)) {
    ts = ticks[0] * MS_PER_SEC + Math.trunc(ticks[1] / TICKS_PER_MS);
    extra = ticks[1] % TICKS_PER_MS;
  } else {
    if (ticks.length <= 4) {
      ts = 0;
    } else {
      ts = parseInt(ticks.slice(0, -4), 10);
    }
    extra = parseInt(ticks.slice(-4), 10);
  }
  const dateObj = new Date(ts - (SECONDS_TO_EPOCH * MS_PER_SEC));
  Object.defineProperty(dateObj, 'getTicks', {
    value: () => extra
  });
  return dateObj;
}
 
function now() {
  const [secs, ns] = nano.now();
  // ~~ is fast truncation for numbers which don't exceed 32 bits
  return toTickObj([secs + SECONDS_TO_EPOCH, ~~(ns / NS_PER_TICK)]);
}
 
module.exports = {
  ticksNow: now,
  ticksAt: at,
  ticksFromDate: from,
  ticksToDate: to
};