Метод fromObject с weekYear

Метод fromObject в библиотеке Luxon используется для создания объекта DateTime на основе набора свойств. Одной из менее очевидных, но крайне важных возможностей является работа с недельным календарём ISO через параметры weekYear, weekNumber и weekday.

Недельный календарь ISO отличается от привычного календаря с месяцами и днями. В нём дата определяется:

  • номером недели;
  • номером дня недели;
  • недельным годом (weekYear).

Такой подход активно используется:

  • в бухгалтерских системах;
  • ERP и CRM;
  • производственном планировании;
  • аналитике;
  • международных стандартах отчётности;
  • системах логистики.

Основы ISO-недель

ISO-8601 определяет особую систему недель:

  • неделя начинается с понедельника;
  • первая неделя года — та, которая содержит первый четверг года;
  • год может содержать 52 или 53 недели.

Из-за этого недельный год (weekYear) может отличаться от обычного календарного года.

Пример:

Дата calendar year weekYear
2021-01-01 2021 2020
2022-01-01 2022 2021
2018-12-31 2018 2019

Базовый синтаксис

DateTime.fromObject({
  weekYear: 2024,
  weekNumber: 10,
  weekday: 3
})

Здесь:

  • weekYear — ISO-недельный год;
  • weekNumber — номер недели;
  • weekday — день недели.

Импорт Luxon

import { DateTime } from "luxon"

Для CommonJS:

const { DateTime } = require("luxon")

Создание даты через weekYear

Пример базового создания

const dt = DateTime.fromObject({
  weekYear: 2024,
  weekNumber: 1,
  weekday: 1
})

console.log(dt.toISODate())

Результат:

2024-01-01

Здесь создаётся:

  • первая ISO-неделя;
  • понедельник;
  • недельного года 2024.

Что означает weekday

Значения weekday:

Значение День
1 Понедельник
2 Вторник
3 Среда
4 Четверг
5 Пятница
6 Суббота
7 Воскресенье

Взаимосвязь weekYear и weekNumber

Пример

const dt = DateTime.fromObject({
  weekYear: 2020,
  weekNumber: 53,
  weekday: 5
})

console.log(dt.toISODate())

Результат:

2021-01-01

Хотя дата находится в 2021 году, ISO-недельный год всё ещё равен 2020.

Это ключевая особенность недельного календаря.


Получение weekYear из существующей даты

const dt = DateTime.local(2021, 1, 1)

console.log(dt.weekYear)
console.log(dt.weekNumber)
console.log(dt.weekday)

Результат:

2020
53
5

Отличие year от weekYear

Обычный календарный год

const dt = DateTime.local(2021, 1, 1)

console.log(dt.year)

Результат:

2021

Недельный год

console.log(dt.weekYear)

Результат:

2020

Почему возникает расхождение

ISO-календарь пытается сохранить полные недели.

Если начало января попадает в «хвост» предыдущей недели, дата относится к предыдущему weekYear.

Аналогично:

  • последние дни декабря могут принадлежать следующему недельному году.

Создание диапазонов недель

Начало недели

const start = DateTime.fromObject({
  weekYear: 2024,
  weekNumber: 15,
  weekday: 1
})

console.log(start.toISODate())

Конец недели

const end = DateTime.fromObject({
  weekYear: 2024,
  weekNumber: 15,
  weekday: 7
})

console.log(end.toISODate())

Работа с бизнес-логикой

Формирование отчёта за ISO-неделю

function getWeekReportDate(weekYear, weekNumber) {
  return DateTime.fromObject({
    weekYear,
    weekNumber,
    weekday: 1
  })
}

Использование зоны времени

Метод fromObject поддерживает передачу временной зоны.

const dt = DateTime.fromObject(
  {
    weekYear: 2024,
    weekNumber: 20,
    weekday: 1
  },
  {
    zone: "Europe/Berlin"
  }
)

console.log(dt.toString())

Использование locale

Локаль влияет на форматирование, но не меняет ISO-логику weekYear.

const dt = DateTime.fromObject(
  {
    weekYear: 2024,
    weekNumber: 1,
    weekday: 1
  },
  {
    locale: "ru"
  }
)

console.log(dt.toLocaleString(DateTime.DATE_FULL))

Ошибки смешивания year и weekYear

Нельзя одновременно использовать:

  • year;
  • month;
  • day;

вместе с:

  • weekYear;
  • weekNumber;
  • weekday.

Неправильный пример

DateTime.fromObject({
  year: 2024,
  month: 5,
  day: 10,
  weekYear: 2024
})

Luxon считает такие данные конфликтующими.


Корректные комбинации

Календарная система

DateTime.fromObject({
  year: 2024,
  month: 5,
  day: 10
})

ISO-недельная система

DateTime.fromObject({
  weekYear: 2024,
  weekNumber: 19,
  weekday: 5
})

Проверка валидности

const dt = DateTime.fromObject({
  weekYear: 2024,
  weekNumber: 60,
  weekday: 1
})

console.log(dt.isValid)
console.log(dt.invalidReason)

Результат:

false
unit out of range

Ограничения weekNumber

ISO-неделя может иметь:

  • от 1 до 52;
  • иногда 53 недели.

Проверка количества недель в году

const weeks = DateTime.local(2020).weeksInWeekYear

console.log(weeks)

Результат:

53

Пример вычисления расписания

function getSprintStart(weekYear, weekNumber) {
  return DateTime.fromObject({
    weekYear,
    weekNumber,
    weekday: 1
  }).startOf("day")
}

Генерация всех дней ISO-недели

function getWeekDays(weekYear, weekNumber) {
  const start = DateTime.fromObject({
    weekYear,
    weekNumber,
    weekday: 1
  })

  return Array.from({ length: 7 }, (_, i) =>
    start.plus({ days: i })
  )
}

Преобразование weekYear в обычную дату

const dt = DateTime.fromObject({
  weekYear: 2025,
  weekNumber: 1,
  weekday: 1
})

console.log(dt.year)
console.log(dt.month)
console.log(dt.day)

Форматирование ISO-недель

Вывод weekYear

const dt = DateTime.local()

console.log(dt.weekYear)
console.log(dt.weekNumber)

Формирование строк отчётности

const dt = DateTime.local()

const reportId = `${dt.weekYear}-W${dt.weekNumber}`

console.log(reportId)

Пример результата:

2024-W18

Сравнение с обычным календарём

Календарный подход

DateTime.fromObject({
  year: 2024,
  month: 1,
  day: 1
})

ISO-недельный подход

DateTime.fromObject({
  weekYear: 2024,
  weekNumber: 1,
  weekday: 1
})

Во втором случае дата вычисляется через ISO-алгоритм недель.


Использование startOf и endOf

const dt = DateTime.fromObject({
  weekYear: 2024,
  weekNumber: 10,
  weekday: 3
})

console.log(dt.startOf("week").toISODate())
console.log(dt.endOf("week").toISODate())

Создание корпоративных календарей

ISO-недели особенно полезны для:

  • Agile-спринтов;
  • финансовых кварталов;
  • производственных циклов;
  • табелей;
  • международных графиков поставок.

Практический пример: Agile-спринт

function createSprint(weekYear, weekNumber) {
  const start = DateTime.fromObject({
    weekYear,
    weekNumber,
    weekday: 1
  })

  const end = start.plus({ days: 13 })

  return {
    start: start.toISODate(),
    end: end.toISODate()
  }
}

Получение текущего weekYear

const current = DateTime.now()

console.log(current.weekYear)

Переход между недельными годами

Конец декабря

const dt = DateTime.local(2024, 12, 31)

console.log(dt.weekYear)
console.log(dt.weekNumber)

Начало января

const dt = DateTime.local(2025, 1, 1)

console.log(dt.weekYear)
console.log(dt.weekNumber)

Внутренний механизм ISO-вычислений

При использовании weekYear библиотека:

  1. определяет первую ISO-неделю;
  2. вычисляет смещение;
  3. находит нужную неделю;
  4. определяет конкретный день.

Из-за этого итоговая дата может находиться:

  • в предыдущем календарном году;
  • в следующем календарном году.

Использование with

const dt = DateTime.local()

const updated = dt.with({
  weekYear: 2025,
  weekNumber: 10,
  weekday: 1
})

console.log(updated.toISODate())

Комбинация с plus и minus

const dt = DateTime.fromObject({
  weekYear: 2024,
  weekNumber: 1,
  weekday: 1
})

console.log(
  dt.plus({ weeks: 1 }).toISODate()
)

console.log(
  dt.minus({ weeks: 1 }).toISODate()
)

Частые ошибки

Использование weekday = 0

DateTime.fromObject({
  weekYear: 2024,
  weekNumber: 10,
  weekday: 0
})

Ошибка:

unit out of range

Использование несуществующей недели

DateTime.fromObject({
  weekYear: 2021,
  weekNumber: 54,
  weekday: 1
})

Проверка ISO-недель перед созданием даты

function isValidWeek(weekYear, weekNumber) {
  const maxWeeks =
    DateTime.local(weekYear).weeksInWeekYear

  return weekNumber >= 1 &&
         weekNumber <= maxWeeks
}

Сериализация

const dt = DateTime.fromObject({
  weekYear: 2024,
  weekNumber: 20,
  weekday: 2
})

console.log(dt.toISO())
console.log(dt.toJSON())

Использование в аналитике

Недельные годы помогают:

  • стабилизировать отчёты;
  • избежать неполных недель;
  • унифицировать статистику;
  • синхронизировать международные системы.

Когда использовать weekYear

weekYear особенно полезен в системах, где основной единицей времени является неделя, а не месяц или календарная дата:

  • Scrum;
  • ERP;
  • BI-аналитика;
  • SAP;
  • производственные календари;
  • финансовые отчёты;
  • логистические платформы;
  • международные корпоративные системы.