var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var dateTrunc_exports = {};
__export(dateTrunc_exports, {
  $dateTrunc: () => $dateTrunc
});
module.exports = __toCommonJS(dateTrunc_exports);
var import_core = require("../../../core");
var import_types = require("../../../types");
var import_util = require("../../../util");
var import_internal = require("./_internal");
const REF_DATE_MILLIS = 9466848e5;
const distanceToBinLowerBound = (value, binSize) => {
  let remainder = value % binSize;
  if (remainder < 0) {
    remainder += binSize;
  }
  return remainder;
};
const DATE_DIFF_FN = {
  day: import_internal.dateDiffDay,
  month: import_internal.dateDiffMonth,
  quarter: import_internal.dateDiffQuarter,
  year: import_internal.dateDiffYear
};
const DAYS_OF_WEEK_RE = /(mon(day)?|tue(sday)?|wed(nesday)?|thu(rsday)?|fri(day)?|sat(urday)?|sun(day)?)/i;
const $dateTrunc = (obj, expr, options) => {
  const {
    date,
    unit,
    binSize: optBinSize,
    timezone,
    startOfWeek: optStartOfWeek
  } = (0, import_core.computeValue)(obj, expr, null, options);
  if ((0, import_util.isNil)(date) || (0, import_util.isNil)(unit)) return null;
  const startOfWeek = (optStartOfWeek ?? "sun").toLowerCase().substring(0, 3);
  (0, import_util.assert)(
    (0, import_util.isDate)(date),
    "$dateTrunc: 'date' must resolve to a valid Date object."
  );
  (0, import_util.assert)(import_types.TIME_UNITS.includes(unit), "$dateTrunc: unit is invalid.");
  (0, import_util.assert)(
    unit != "week" || DAYS_OF_WEEK_RE.test(startOfWeek),
    `$dateTrunc: startOfWeek '${startOfWeek}' is not a valid.`
  );
  (0, import_util.assert)(
    (0, import_util.isNil)(optBinSize) || optBinSize > 0,
    "$dateTrunc requires 'binSize' to be greater than 0, but got value 0."
  );
  const binSize = optBinSize ?? 1;
  switch (unit) {
    case "millisecond":
    case "second":
    case "minute":
    case "hour": {
      const binSizeMillis = binSize * import_internal.TIMEUNIT_IN_MILLIS[unit];
      const shiftedDate = date.getTime() - REF_DATE_MILLIS;
      return new Date(
        date.getTime() - distanceToBinLowerBound(shiftedDate, binSizeMillis)
      );
    }
    default: {
      (0, import_util.assert)(binSize <= 1e11, "dateTrunc unsupported binSize value");
      const d = new Date(date);
      const refPointDate = new Date(REF_DATE_MILLIS);
      let distanceFromRefPoint = 0;
      if (unit == "week") {
        const refPointDayOfWeek = (0, import_internal.isoWeekday)(refPointDate, startOfWeek);
        const daysToAdjustBy = (import_internal.DAYS_PER_WEEK - refPointDayOfWeek) % import_internal.DAYS_PER_WEEK;
        refPointDate.setTime(
          refPointDate.getTime() + daysToAdjustBy * import_internal.TIMEUNIT_IN_MILLIS.day
        );
        distanceFromRefPoint = (0, import_internal.dateDiffWeek)(refPointDate, d, startOfWeek);
      } else {
        distanceFromRefPoint = DATE_DIFF_FN[unit](refPointDate, d);
      }
      const binLowerBoundFromRefPoint = distanceFromRefPoint - distanceToBinLowerBound(distanceFromRefPoint, binSize);
      const newDate = (0, import_internal.dateAdd)(
        refPointDate,
        unit,
        binLowerBoundFromRefPoint,
        timezone
      );
      const minuteOffset = (0, import_internal.parseTimezone)(timezone);
      (0, import_internal.adjustDate)(newDate, -minuteOffset);
      return newDate;
    }
  }
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  $dateTrunc
});
