@digital-magic/io-ts-local-date-time
Version:
LocalDate, LocalTime and TimeSlot types and utilities for TS
79 lines (78 loc) • 4.05 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.hasOverlaps = exports.slotOverlaps = exports.timeSlotOrd = exports.secondsTimeSlotToTimeSlot = exports.secondsTimeSlotToTimeSlotEncoder = exports.SecondsTimeSlotToTimeSlotDecoder = exports.TimeSlot = exports.SecondsTimeSlot = void 0;
const t = __importStar(require("io-ts"));
const O = __importStar(require("fp-ts/lib/Option"));
const A = __importStar(require("fp-ts/lib/ReadonlyArray"));
const E = __importStar(require("fp-ts/lib/Either"));
const pipeable_1 = require("fp-ts/lib/pipeable");
const Ord_1 = require("fp-ts/lib/Ord");
const Apply_1 = require("fp-ts/lib/Apply");
const localtime_1 = require("./localtime");
const io_ts_extensions_1 = require("@digital-magic/io-ts-extensions");
exports.SecondsTimeSlot = t.type({
timeSince: t.number,
timeBefore: t.number
}, 'TimeSlot');
exports.TimeSlot = t.type({
timeSince: localtime_1.LocalTime,
timeBefore: localtime_1.LocalTime
}, 'TimeSlot');
exports.SecondsTimeSlotToTimeSlotDecoder = io_ts_extensions_1.decoder('ApiTimeSlotToTimeSlot', (u, c) => E.flatten(E.either.map(exports.TimeSlot.validate(u, c), (v) => {
const timeSince = localtime_1.SecondsFromLocalTimeDecoder.validate(v.timeSince, c);
const timeBefore = localtime_1.SecondsFromLocalTimeDecoder.validate(v.timeBefore, c);
return pipeable_1.pipe(Apply_1.sequenceT(E.either)(timeSince, timeBefore), E.map(([ts, tb]) => {
return {
timeSince: ts,
timeBefore: tb
};
}));
})));
const secondsTimeSlotToTimeSlotEncoder = (dateFormat) => io_ts_extensions_1.encoder((v) => {
return {
timeSince: localtime_1.secondsFromLocalTimeEncoder(dateFormat).encode(v.timeSince),
timeBefore: localtime_1.secondsFromLocalTimeEncoder(dateFormat).encode(v.timeBefore)
};
});
exports.secondsTimeSlotToTimeSlotEncoder = secondsTimeSlotToTimeSlotEncoder;
// Example how to build codec
/*
export const SecondsTimeSlotToTimeSlot = codec<SecondsTimeSlot, TimeSlot, TimeSlot>(SecondsTimeSlotToTimeSlotDecoder, secondsTimeSlotToTimeSlotEncoder(''), SecondsTimeSlot.is)
*/
exports.secondsTimeSlotToTimeSlot = io_ts_extensions_1.unsafeDecode(exports.SecondsTimeSlotToTimeSlotDecoder);
exports.timeSlotOrd = Ord_1.contramap((v) => localtime_1.secondsFromLocalTime(v.timeBefore))(Ord_1.ordNumber);
function slotOverlaps(x, y) {
return x.timeSince <= y.timeBefore && y.timeSince <= x.timeBefore;
}
exports.slotOverlaps = slotOverlaps;
function pair(first, second) {
return { first, second };
}
function getLastTimeSlot(acc) {
return pipeable_1.pipe(acc, A.last, O.map((v) => v.second));
}
function hasOverlaps(slots) {
return pipeable_1.pipe(slots, A.sort(exports.timeSlotOrd), A.reduce([], (acc, current) => acc.concat(pair(getLastTimeSlot(acc), current))), A.filterMap(({ first, second }) => pipeable_1.pipe(first, O.map((v) => pair(v, second)))),
// TODO: Not a type safe code: secondsTimeSlotToTimeSlot - consider refactoring
A.map(({ first, second }) => slotOverlaps(exports.secondsTimeSlotToTimeSlot(first), exports.secondsTimeSlotToTimeSlot(second)))).some((v) => v);
}
exports.hasOverlaps = hasOverlaps;