cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

create.js (4335B)


      1import { Duration, isDuration } from './constructor';
      2import isNumber from '../utils/is-number';
      3import toInt from '../utils/to-int';
      4import absRound from '../utils/abs-round';
      5import hasOwnProp from '../utils/has-own-prop';
      6import { DATE, HOUR, MINUTE, SECOND, MILLISECOND } from '../units/constants';
      7import { cloneWithOffset } from '../units/offset';
      8import { createLocal } from '../create/local';
      9import { createInvalid as invalid } from './valid';
     10
     11// ASP.NET json date format regex
     12var aspNetRegex = /^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,
     13    // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
     14    // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
     15    // and further modified to allow for strings containing both week and day
     16    isoRegex =
     17        /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
     18
     19export function createDuration(input, key) {
     20    var duration = input,
     21        // matching against regexp is expensive, do it on demand
     22        match = null,
     23        sign,
     24        ret,
     25        diffRes;
     26
     27    if (isDuration(input)) {
     28        duration = {
     29            ms: input._milliseconds,
     30            d: input._days,
     31            M: input._months,
     32        };
     33    } else if (isNumber(input) || !isNaN(+input)) {
     34        duration = {};
     35        if (key) {
     36            duration[key] = +input;
     37        } else {
     38            duration.milliseconds = +input;
     39        }
     40    } else if ((match = aspNetRegex.exec(input))) {
     41        sign = match[1] === '-' ? -1 : 1;
     42        duration = {
     43            y: 0,
     44            d: toInt(match[DATE]) * sign,
     45            h: toInt(match[HOUR]) * sign,
     46            m: toInt(match[MINUTE]) * sign,
     47            s: toInt(match[SECOND]) * sign,
     48            ms: toInt(absRound(match[MILLISECOND] * 1000)) * sign, // the millisecond decimal point is included in the match
     49        };
     50    } else if ((match = isoRegex.exec(input))) {
     51        sign = match[1] === '-' ? -1 : 1;
     52        duration = {
     53            y: parseIso(match[2], sign),
     54            M: parseIso(match[3], sign),
     55            w: parseIso(match[4], sign),
     56            d: parseIso(match[5], sign),
     57            h: parseIso(match[6], sign),
     58            m: parseIso(match[7], sign),
     59            s: parseIso(match[8], sign),
     60        };
     61    } else if (duration == null) {
     62        // checks for null or undefined
     63        duration = {};
     64    } else if (
     65        typeof duration === 'object' &&
     66        ('from' in duration || 'to' in duration)
     67    ) {
     68        diffRes = momentsDifference(
     69            createLocal(duration.from),
     70            createLocal(duration.to)
     71        );
     72
     73        duration = {};
     74        duration.ms = diffRes.milliseconds;
     75        duration.M = diffRes.months;
     76    }
     77
     78    ret = new Duration(duration);
     79
     80    if (isDuration(input) && hasOwnProp(input, '_locale')) {
     81        ret._locale = input._locale;
     82    }
     83
     84    if (isDuration(input) && hasOwnProp(input, '_isValid')) {
     85        ret._isValid = input._isValid;
     86    }
     87
     88    return ret;
     89}
     90
     91createDuration.fn = Duration.prototype;
     92createDuration.invalid = invalid;
     93
     94function parseIso(inp, sign) {
     95    // We'd normally use ~~inp for this, but unfortunately it also
     96    // converts floats to ints.
     97    // inp may be undefined, so careful calling replace on it.
     98    var res = inp && parseFloat(inp.replace(',', '.'));
     99    // apply sign while we're at it
    100    return (isNaN(res) ? 0 : res) * sign;
    101}
    102
    103function positiveMomentsDifference(base, other) {
    104    var res = {};
    105
    106    res.months =
    107        other.month() - base.month() + (other.year() - base.year()) * 12;
    108    if (base.clone().add(res.months, 'M').isAfter(other)) {
    109        --res.months;
    110    }
    111
    112    res.milliseconds = +other - +base.clone().add(res.months, 'M');
    113
    114    return res;
    115}
    116
    117function momentsDifference(base, other) {
    118    var res;
    119    if (!(base.isValid() && other.isValid())) {
    120        return { milliseconds: 0, months: 0 };
    121    }
    122
    123    other = cloneWithOffset(other, base);
    124    if (base.isBefore(other)) {
    125        res = positiveMomentsDifference(base, other);
    126    } else {
    127        res = positiveMomentsDifference(other, base);
    128        res.milliseconds = -res.milliseconds;
    129        res.months = -res.months;
    130    }
    131
    132    return res;
    133}