Создание даты из номера недели

Во многих странах и бизнес-системах календарные операции строятся не вокруг конкретного дня месяца, а вокруг номера недели. Такой подход активно используется в:

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

Библиотека Luxon позволяет создавать даты не только из привычных компонентов (year, month, day), но и из:

  • номера недели;
  • номера дня внутри недели;
  • ISO-недели;
  • локальных недель.

Это особенно важно при работе с ISO-8601, где неделя считается основной единицей календаря.


ISO-недели

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

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

Например:

Дата ISO-неделя
2024-01-01 1
2024-12-31 1 (следующего ISO-года)
2025-01-03 1

Из-за этого ISO-год и календарный год могут отличаться.


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

Для создания даты из номера недели используется метод DateTime.fromObject().

import { DateTime } from "luxon";

const date = DateTime.fromObject({
  weekYear: 2025,
  weekNumber: 10,
  weekday: 3
});

console.log(date.toISO());

Результат:

2025-03-05T00:00:00.000+03:00

Значения параметров

weekYear

ISO-год.

weekYear: 2025

Не всегда совпадает с обычным календарным годом.


weekNumber

Номер недели в году.

weekNumber: 10

Допустимый диапазон:

1 - 52

или

1 - 53

в зависимости от года.


weekday

Номер дня недели.

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

Пример:

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

console.log(monday.toISODate());

Создание первого дня недели

Чаще всего требуется получить понедельник определённой недели.

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

console.log(startOfWeek.toISODate());

Создание последнего дня недели

Для воскресенья используется weekday: 7.

const endOfWeek = DateTime.fromObject({
  weekYear: 2025,
  weekNumber: 20,
  weekday: 7
});

console.log(endOfWeek.toISODate());

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

Иногда необходимо построить массив всех дней недели.

const days = [];

for (let i = 1; i <= 7; i++) {
  days.push(
    DateTime.fromObject({
      weekYear: 2025,
      weekNumber: 15,
      weekday: i
    }).toISODate()
  );
}

console.log(days);

Результат:

[
  '2025-04-07',
  '2025-04-08',
  '2025-04-09',
  '2025-04-10',
  '2025-04-11',
  '2025-04-12',
  '2025-04-13'
]

Создание даты без weekday

Если weekday не указан, Luxon использует понедельник.

const date = DateTime.fromObject({
  weekYear: 2025,
  weekNumber: 8
});

console.log(date.toISODate());

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

Некоторые годы содержат 53 недели, некоторые — нет.

Некорректная комбинация создаёт невалидную дату.

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

console.log(date.isValid);

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

if (!date.isValid) {
  console.log(date.invalidReason);
}

Возможный результат:

unit out of range

Работа с часовыми поясами

Дата может быть создана сразу в нужной временной зоне.

const date = DateTime.fromObject(
  {
    weekYear: 2025,
    weekNumber: 10,
    weekday: 5
  },
  {
    zone: "Europe/Berlin"
  }
);

console.log(date.toString());

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

const utcDate = DateTime.fromObject(
  {
    weekYear: 2025,
    weekNumber: 1,
    weekday: 1
  },
  {
    zone: "utc"
  }
);

console.log(utcDate.toISO());

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

Одно из самых распространённых применений.

function getDateFromWeek(year, week, weekday = 1) {
  return DateTime.fromObject({
    weekYear: year,
    weekNumber: week,
    weekday
  });
}

const result = getDateFromWeek(2025, 30, 4);

console.log(result.toISODate());

Получение даты начала квартальной недели

Пример вычисления даты начала рабочей недели.

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

console.log(quarterWeek.startOf("day").toISO());

Построение расписания по неделям

const meetings = [];

for (let week = 1; week <= 4; week++) {
  meetings.push(
    DateTime.fromObject({
      weekYear: 2025,
      weekNumber: week,
      weekday: 2
    }).toFormat("yyyy-MM-dd")
  );
}

console.log(meetings);

Работа с ISO-календарём

Luxon использует ISO-логику по умолчанию.

Это означает:

  • понедельник считается первым днём недели;
  • ISO-недели вычисляются автоматически;
  • поддерживается стандарт ISO-8601.

Отличие от обычного создания даты

Обычное создание:

DateTime.fromObject({
  year: 2025,
  month: 3,
  day: 5
});

Создание через неделю:

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

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


Преобразование существующей даты в номер недели

const now = DateTime.now();

console.log(now.weekYear);
console.log(now.weekNumber);
console.log(now.weekday);

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

2025
18
5

Восстановление даты из сохранённых данных

Частая ситуация — хранение только:

  • года недели;
  • номера недели;
  • номера дня.
const saved = {
  weekYear: 2025,
  weekNumber: 40,
  weekday: 2
};

const restored = DateTime.fromObject(saved);

console.log(restored.toISODate());

Создание календарной сетки

const calendar = [];

for (let week = 1; week <= 5; week++) {
  const row = [];

  for (let day = 1; day <= 7; day++) {
    row.push(
      DateTime.fromObject({
        weekYear: 2025,
        weekNumber: week,
        weekday: day
      }).toISODate()
    );
  }

  calendar.push(row);
}

console.log(calendar);

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

const date = DateTime.fromObject({
  weekYear: 2025,
  weekNumber: 22,
  weekday: 6
});

console.log(
  date.toFormat("cccc, dd LLLL yyyy")
);

Результат:

Saturday, 31 May 2025

Получение начала и конца недели

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

const sunday = monday.plus({ days: 6 });

console.log(monday.toISODate());
console.log(sunday.toISODate());

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

const weeks = [];

for (let week = 20; week <= 25; week++) {
  weeks.push(
    DateTime.fromObject({
      weekYear: 2025,
      weekNumber: week,
      weekday: 1
    }).toISODate()
  );
}

console.log(weeks);

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

Недельные идентификаторы удобны для:

  • агрегации статистики;
  • построения отчётов;
  • анализа продаж;
  • планирования спринтов;
  • расчёта KPI;
  • временных рядов.

Пример структуры:

{
  weekYear: 2025,
  weekNumber: 12,
  revenue: 150000
}

Проверка ISO-компонентов

const date = DateTime.now();

console.log({
  weekYear: date.weekYear,
  weekNumber: date.weekNumber,
  weekday: date.weekday
});

Создание даты из ISO-недели и времени

Можно одновременно указать время.

const date = DateTime.fromObject({
  weekYear: 2025,
  weekNumber: 35,
  weekday: 4,
  hour: 14,
  minute: 30
});

console.log(date.toISO());

Ограничения при смешивании единиц

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

  • year;
  • month;
  • day;

и:

  • weekYear;
  • weekNumber;
  • weekday.

Некорректный пример:

DateTime.fromObject({
  year: 2025,
  month: 5,
  weekNumber: 10
});

Это приведёт к ошибке валидации.


Создание даты из номера рабочей недели

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

const workWeek = getWorkWeekStart(2025, 42);

console.log(workWeek.toISODate());

Практический пример: планирование спринтов

function sprintStart(weekNumber) {
  return DateTime.fromObject({
    weekYear: 2025,
    weekNumber,
    weekday: 1
  });
}

const sprint = sprintStart(16);

console.log(
  sprint.toFormat("dd LLL yyyy")
);

Практический пример: расписание поставок

const delivery = DateTime.fromObject({
  weekYear: 2025,
  weekNumber: 28,
  weekday: 5,
  hour: 9
});

console.log(delivery.toISO());

Практический пример: недельная отчётность

function buildReportDate(weekYear, weekNumber) {
  return DateTime.fromObject({
    weekYear,
    weekNumber,
    weekday: 7
  });
}

const reportDate = buildReportDate(2025, 50);

console.log(reportDate.toISODate());