"use strict";
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parse = exports.getRussianWeekDay = exports.normalizeDate = void 0;
/* eslint no-continue: 0 */
var get_days_in_month_1 = __importDefault(require("date-fns/get_days_in_month"));
var DAYS_IN_WEEK = 7;
/**
 * Нормализирует дату, возвращает Date вне завистимости от входных данных.
 *
 * @param date Дата для нормализации.
 */
function normalizeDate(date) {
    return new Date(date);
}
exports.normalizeDate = normalizeDate;
/**
 * Возвращает «правильный» индекс дня недели, 0 - пн, 1 - вт и так далее.
 *
 * @param date Дата, из которой нужно получить день недели.
 */
function getRussianWeekDay(date) {
    var sunday = 0;
    var foreignWeekDayIndex = date.getDay();
    return foreignWeekDayIndex === sunday
        ? DAYS_IN_WEEK - 1
        : foreignWeekDayIndex - 1;
}
exports.getRussianWeekDay = getRussianWeekDay;
var PARSE_TOKENS = [
    { type: 'date', regex: /^\d{2}/, formatRegex: /^DD/ },
    { type: 'date', regex: /^\d{1,2}/, formatRegex: /^D/ },
    { type: 'month', regex: /^\d{2}/, formatRegex: /^MM/ },
    { type: 'month', regex: /^\d{1,2}/, formatRegex: /^M/ },
    { type: 'year', regex: /^\d{4}/, formatRegex: /^YYYY/ },
];
/**
 * Возвращает граничные значения для дня, месяца, года.
 *
 * @param month Месяц в котором нужно получить максимально возможное число дней.
 * @param year Год месяца в котором нужно получить максимально возможное число дней.
 * @returns Лимиты для переданной даты
 */
function getLimits(month, year) {
    return {
        date: { min: 1, max: get_days_in_month_1.default(new Date(year, month - 1)) },
        month: { min: 1, max: 12 },
        year: { min: 1, max: Number.MAX_SAFE_INTEGER },
    };
}
var PARSER_CACHE = {};
/**
 * Разбирает строку с форматом даты.
 *
 * @param format формат даты для разбора.
 */
function parseFormat(format) {
    if (PARSER_CACHE[format]) {
        return PARSER_CACHE[format];
    }
    var parser = [];
    var processingFormat = format;
    while (processingFormat.length > 0) {
        /* eslint no-loop-func: 0 */
        var matchedToken = PARSE_TOKENS.find(function (t) { return processingFormat.match(t.formatRegex); });
        if (matchedToken) {
            parser.push(matchedToken);
            processingFormat = processingFormat.replace(matchedToken.formatRegex, '');
        }
        else {
            parser.push({ type: 'delimiter', value: processingFormat[0] });
            processingFormat = processingFormat.substring(1);
        }
    }
    PARSER_CACHE[format] = parser;
    return parser;
}
/**
 * Разбирает дату из строки по заданному формату.
 * Допустимые элементы формата:
 * D - дата, в формате 1-31
 * DD - дата, в формате 01-31,
 * M - месяц, в формате 1-12,
 * MM - месяц, в формате 01-12
 * YYYY - год
 * В качестве разделителей между элементами даты могут выступать любые символы, не являющиеся частью формата.
 *
 * @param input Входная строка для разбора.
 * @param format Формат, который будет использоваться для разбора.
 * @param strict Запрещать ли значения, выходящие за пределы логических ограничений месяцев/дней.
 * В случае если strict=false 22 месяц будет интерпретироваться как год и 10 месяцев.
 */
function parse(input, format, strict) {
    if (format === void 0) { format = 'DD.MM.YYYY'; }
    if (strict === void 0) { strict = true; }
    var parsedFormat = parseFormat(format);
    var parsedResult = {};
    for (var i = 0; i < parsedFormat.length; i++) {
        var token = parsedFormat[i];
        if (token.type === 'delimiter') {
            if (input[0] !== token.value) {
                return new Date('invalid');
            }
            // eslint-disable-next-line no-param-reassign
            input = input.substring(1);
            continue;
        }
        var match = input.match(token.regex);
        if (!match) {
            return new Date('invalid');
        }
        parsedResult[token.type] = parseInt(match[0], 10);
        // eslint-disable-next-line no-param-reassign
        input = input.replace(token.regex, '');
    }
    var _a = getLimits(parsedResult.month, parsedResult.year), dateLimits = _a.date, monthLimits = _a.month, yearLimits = _a.year;
    if (strict && (parsedResult.date > dateLimits.max || parsedResult.date < dateLimits.min
        || parsedResult.month > monthLimits.max || parsedResult.month < monthLimits.min
        || parsedResult.year > yearLimits.max || parsedResult.year < yearLimits.min)) {
        return new Date('invalid');
    }
    return new Date(parsedResult.year, parsedResult.month - 1, parsedResult.date || 1);
}
exports.parse = parse;

//# sourceMappingURL=date-utils.js.map
