Интерфейс TemporalQuery в библиотеке js-joda
предназначен для извлечения данных из объектов временной модели через
универсальный механизм запросов. Он используется совместно с методом
query() и позволяет получать информацию о временном объекте
без прямого обращения к его внутренней структуре.
Подход основан на концепции из Java Time API: объект времени
предоставляет данные, а запрос (TemporalQuery) определяет,
какую именно информацию необходимо извлечь.
Основная сигнатура:
temporal.query(query)
Где:
temporal — любой объект, реализующий
TemporalAccessorquery — функция или объект запросаПример:
const { LocalDate, TemporalQueries } = require('@js-joda/core')
const date = LocalDate.parse('2025-03-15')
const chronology = date.query(TemporalQueries.chronology())
console.log(chronology)
TemporalAccessorTemporalQuery работает только с объектами, реализующими
интерфейс TemporalAccessor.
К таким объектам относятся:
LocalDateLocalTimeLocalDateTimeZonedDateTimeOffsetDateTimeYearYearMonthMonthDayInstantКаждый из них предоставляет метод:
query(query)
Внутри метод передаёт текущий объект в запрос.
Упрощённая схема:
query.queryFrom(temporal)
TemporalQueryВ Js-joda запрос обычно представляет собой функцию.
Простейший пример:
const { LocalDate } = require('@js-joda/core')
const date = LocalDate.now()
const query = temporal => temporal.toString()
const result = date.query(query)
console.log(result)
Здесь:
LocalDate передаётся в функциюTemporalQueriesБиблиотека содержит набор стандартных запросов в классе
TemporalQueries.
Подключение:
const { TemporalQueries } = require('@js-joda/core')
Доступные запросы:
| Запрос | Назначение |
|---|---|
chronology() |
календарная система |
localDate() |
извлечение LocalDate |
localTime() |
извлечение LocalTime |
offset() |
временное смещение |
precision() |
точность временного объекта |
zone() |
зона |
zoneId() |
идентификатор зоны |
LocalDateЗапрос localDate() извлекает дату из объекта.
Пример с LocalDateTime:
const {
LocalDateTime,
TemporalQueries
} = require('@js-joda/core')
const dt = LocalDateTime.parse('2025-04-10T12:30:45')
const date = dt.query(TemporalQueries.localDate())
console.log(date.toString())
Результат:
2025-04-10
LocalTimeАналогично работает localTime().
const {
LocalDateTime,
TemporalQueries
} = require('@js-joda/core')
const dt = LocalDateTime.parse('2025-04-10T12:30:45')
const time = dt.query(TemporalQueries.localTime())
console.log(time.toString())
Результат:
12:30:45
zone()Запрос возвращает объект зоны времени.
const {
ZonedDateTime,
ZoneId,
TemporalQueries
} = require('@js-joda/core')
const zdt = ZonedDateTime.now(
ZoneId.of('Europe/Berlin')
)
const zone = zdt.query(TemporalQueries.zone())
console.log(zone.toString())
zoneId()Извлекает идентификатор зоны.
const zoneId = zdt.query(
TemporalQueries.zoneId()
)
console.log(zoneId.id())
Результат:
Europe/Berlin
Запрос offset() возвращает ZoneOffset.
const {
OffsetDateTime,
ZoneOffset,
TemporalQueries
} = require('@js-joda/core')
const dt = OffsetDateTime.now(
ZoneOffset.ofHours(3)
)
const offset = dt.query(
TemporalQueries.offset()
)
console.log(offset.toString())
Результат:
+03:00
precision()Позволяет узнать минимальную единицу времени, поддерживаемую объектом.
const {
LocalDate,
TemporalQueries
} = require('@js-joda/core')
const date = LocalDate.now()
const precision = date.query(
TemporalQueries.precision()
)
console.log(precision.toString())
Для LocalDate результат:
Days
Для LocalTime:
Nanos
Главная ценность TemporalQuery — возможность создавать
специализированные запросы.
const { LocalDate } = require('@js-joda/core')
const quarterQuery = temporal => {
const month = temporal.getMonthValue()
return Math.ceil(month / 3)
}
const date = LocalDate.parse('2025-08-11')
console.log(date.query(quarterQuery))
Результат:
3
const { LocalDate } = require('@js-joda/core')
const seasonQuery = temporal => {
const month = temporal.getMonthValue()
if ([12, 1, 2].includes(month)) {
return 'winter'
}
if ([3, 4, 5].includes(month)) {
return 'spring'
}
if ([6, 7, 8].includes(month)) {
return 'summer'
}
return 'autumn'
}
const date = LocalDate.parse('2025-10-20')
console.log(date.query(seasonQuery))
TemporalQuery может возвращать любые структуры
данных.
const { ZonedDateTime } = require('@js-joda/core')
const infoQuery = temporal => ({
year: temporal.year(),
month: temporal.monthValue(),
day: temporal.dayOfMonth()
})
const now = ZonedDateTime.now()
console.log(now.query(infoQuery))
Результат:
{
year: 2025,
month: 5,
day: 25
}
При создании универсальных запросов необходимо учитывать, что разные типы поддерживают разные поля.
Например:
LocalDate не содержит времениLocalTime не содержит датыYear содержит только годconst {
ChronoField,
LocalDate
} = require('@js-joda/core')
const safeHourQuery = temporal => {
if (
temporal.isSupported(
ChronoField.HOUR_OF_DAY
)
) {
return temporal.get(
ChronoField.HOUR_OF_DAY
)
}
return null
}
const date = LocalDate.now()
console.log(date.query(safeHourQuery))
Результат:
null
Запросы удобно использовать как отдельный слой извлечения данных.
const {
ZonedDateTime
} = require('@js-joda/core')
const datePartQuery = temporal => ({
year: temporal.year(),
month: temporal.monthValue(),
day: temporal.dayOfMonth()
})
const timePartQuery = temporal => ({
hour: temporal.hour(),
minute: temporal.minute()
})
const zdt = ZonedDateTime.now()
console.log(zdt.query(datePartQuery))
console.log(zdt.query(timePartQuery))
InstantInstant содержит только UTC-время без календарной
системы и зоны.
Поэтому некоторые запросы возвращают null.
const {
Instant,
TemporalQueries
} = require('@js-joda/core')
const instant = Instant.now()
console.log(
instant.query(
TemporalQueries.localDate()
)
)
Результат:
null
Это связано с тем, что Instant не знает локальную дату
без временной зоны.
query()Метод query():
Упрощённая модель:
query(query) {
return query.queryFrom(this)
}
В Js-joda вместо полноценного интерфейса обычно используется функция.
const {
ZonedDateTime,
TemporalQueries
} = require('@js-joda/core')
const zdt = ZonedDateTime.now()
const analysisQuery = temporal => ({
date: temporal.query(
TemporalQueries.localDate()
),
time: temporal.query(
TemporalQueries.localTime()
),
zone: temporal.query(
TemporalQueries.zoneId()
),
precision: temporal.query(
TemporalQueries.precision()
)
})
console.log(
zdt.query(analysisQuery)
)
const {
ChronoField
} = require('@js-joda/core')
const universalDateQuery = temporal => {
const supportsDate =
temporal.isSupported(
ChronoField.YEAR
)
if (!supportsDate) {
return null
}
return {
year: temporal.get(
ChronoField.YEAR
),
month: temporal.get(
ChronoField.MONTH_OF_YEAR
),
day: temporal.get(
ChronoField.DAY_OF_MONTH
)
}
}
Такой запрос можно применять к:
LocalDateLocalDateTimeZonedDateTimeOffsetDateTimeTemporalQuery от TemporalFieldЭти механизмы решают разные задачи.
TemporalFieldИспользуется для получения конкретного поля:
date.get(ChronoField.YEAR)
Возвращает строго определённое значение.
TemporalQueryИспользуется для извлечения произвольной информации:
date.query(customQuery)
Может возвращать:
TemporalQueryTemporalQuery особенно полезен в следующих случаях:
TemporalQuery только читает данные.
Изменение temporal-объектов невозможно.
nullНекоторые запросы не применимы к определённым типам.
Например:
Instant.now().query(
TemporalQueries.zone()
)
Вернёт:
null
При написании универсальных запросов всегда требуется учитывать:
temporal.isSupported(field)
Без этой проверки возможны исключения.
В крупных проектах запросы часто выносятся в отдельный модуль.
Пример:
// queries.js
exports.quarterQuery = temporal => {
return Math.ceil(
temporal.getMonthValue() / 3
)
}
exports.isWeekendQuery = temporal => {
const day = temporal.dayOfWeek().value()
return day === 6 || day === 7
}
Использование:
const {
quarterQuery,
isWeekendQuery
} = require('./queries')
const date = LocalDate.now()
console.log(date.query(quarterQuery))
console.log(date.query(isWeekendQuery))
TemporalQueryTemporalQuery реализует паттерн Query Object.
Преимущества подхода:
Механизм особенно полезен при построении: