При работе с календарём Pikaday состояние выбранной даты часто
требуется сохранять между перезагрузками страницы, переходами по
интерфейсу или повторными визитами пользователя. Для этого используется
механизм localStorage, позволяющий хранить данные в
браузере в виде строковых значений с долговременной доступностью.
Pikaday оперирует объектами Date, однако
localStorage поддерживает только строковый формат. Поэтому
выбранная дата преобразуется в сериализованный вид перед сохранением и
обратно восстанавливается при загрузке.
Наиболее устойчивыми форматами считаются:
YYYY-MM-DDTHH:mm:ss.sssZ)YYYY-MM-DD для упрощённых сценариевПрактика показывает, что ISO-строка обеспечивает лучшую совместимость
при восстановлении через new Date().
Pikaday предоставляет хук onSelect, который вызывается
при выборе даты. Именно в этом месте удобно синхронизировать состояние с
localStorage.
const picker = new Pikaday({
field: document.getElementById('date-input'),
onSelect: function(date) {
const isoDate = date.toISOString();
localStorage.setItem('selectedDate', isoDate);
}
});
В данном сценарии каждая новая выборка даты перезаписывает предыдущее значение, обеспечивая актуальность состояния.
При повторной загрузке страницы необходимо проверить наличие
сохранённого значения и передать его в Pikaday через метод
setDate.
const savedDate = localStorage.getItem('selectedDate');
const picker = new Pikaday({
field: document.getElementById('date-input'),
onSelect: function(date) {
localStorage.setItem('selectedDate', date.toISOString());
}
});
if (savedDate) {
const parsedDate = new Date(savedDate);
picker.setDate(parsedDate);
}
Такой подход обеспечивает синхронное восстановление UI календаря и значения в поле ввода.
В случаях, когда время не имеет значения, более удобным является хранение даты без временной составляющей.
function formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
function parseDate(str) {
const [year, month, day] = str.split('-').map(Number);
return new Date(year, month - 1, day);
}
Использование такого формата уменьшает риск ошибок, связанных с часовыми поясами.
const picker = new Pikaday({
field: document.getElementById('date-input'),
onSelect: function(date) {
localStorage.setItem('selectedDate', formatDate(date));
}
});
const saved = localStorage.getItem('selectedDate');
if (saved) {
picker.setDate(parseDate(saved));
}
При отсутствии сохранённого состояния необходимо избегать передачи
некорректных значений в setDate. Pikaday ожидает либо
валидный объект Date, либо null.
const saved = localStorage.getItem('selectedDate');
if (saved !== null) {
const date = new Date(saved);
if (!isNaN(date.getTime())) {
picker.setDate(date);
}
}
Проверка валидности даты предотвращает появление некорректного состояния интерфейса.
При использовании нескольких экземпляров Pikaday на одной странице возможно централизованное хранение состояния, если требуется единая логика выбора.
function bindPicker(picker, storageKey) {
picker.onSel ect = function(date) {
localStorage.setItem(storageKey, date.toISOString());
};
const saved = localStorage.getItem(storageKey);
if (saved) {
picker.setDate(new Date(saved));
}
}
Применение:
const startPicker = new Pikaday({
field: document.getElementById('start')
});
const endPicker = new Pikaday({
field: document.getElementById('end')
});
bindPicker(startPicker, 'startDate');
bindPicker(endPicker, 'endDate');
Такой подход обеспечивает независимое хранение состояний для каждого поля.
При реализации выбора диапазона необходимо сохранять два значения: начало и конец периода.
function saveRange(start, end) {
localStorage.setItem('rangeStart', start ? start.toISOString() : '');
localStorage.setItem('rangeEnd', end ? end.toISOString() : '');
}
Восстановление:
const start = localStorage.getItem('rangeStart');
const end = localStorage.getItem('rangeEnd');
if (start) pickerStart.setDate(new Date(start));
if (end) pickerEnd.setDate(new Date(end));
Важно учитывать пустые значения, которые обозначают отсутствие выбранной границы.
При необходимости сброса календаря и локального состояния
используется удаление ключей из localStorage.
localStorage.removeItem('selectedDate');
picker.setDate(null);
В сценариях с диапазоном:
localStorage.removeItem('rangeStart');
localStorage.removeItem('rangeEnd');
После очистки календарь возвращается в исходное состояние без выбранных значений.
localStorage синхронизируется между вкладками через
событие storage. Это позволяет обновлять Pikaday в реальном
времени при изменении данных в другой вкладке.
window.addEventListener('storage', function(event) {
if (event.key === 'selectedDate') {
const newValue = event.newValue;
if (newValue) {
picker.setDate(new Date(newValue));
} else {
picker.setDate(null);
}
}
});
Такой механизм обеспечивает согласованность состояния интерфейса между сессиями.
При смешивании форматов хранения возможно возникновение ошибок парсинга. Для предотвращения этого применяется единая стратегия сериализации.
function safeParseDate(value) {
const date = new Date(value);
return isNaN(date.getTime()) ? null : date;
}
Использование централизованного парсера упрощает поддержку и снижает вероятность некорректного восстановления состояния.
Pikaday поддерживает форматирование через toString и
parse, что позволяет согласовать отображение и хранение
данных.
const picker = new Pikaday({
field: document.getElementById('date-input'),
toString(date) {
return formatDate(date);
},
parse(dateString) {
return parseDate(dateString);
},
onSelect(date) {
localStorage.setItem('selectedDate', formatDate(date));
}
});
Такой подход обеспечивает единый формат на всех уровнях: отображение, хранение и восстановление.
При использовании ISO-строк важно учитывать влияние временной зоны. В некоторых случаях дата может смещаться при восстановлении из-за UTC-конвертации.
Альтернативный подход заключается в хранении локальной даты без времени:
function toLocalISO(date) {
return new Date(date.getTime() - date.getTimezoneOffset() * 60000)
.toISOString()
.split('T')[0];
}
Этот метод фиксирует только календарную часть, исключая смещение времени.
При частом изменении даты возможны избыточные записи в хранилище. Для уменьшения нагрузки применяется проверка изменения значения перед сохранением.
let lastSaved = null;
picker.onSel ect = function(date) {
const value = date.toISOString();
if (value !== lastSaved) {
lastSaved = value;
localStorage.setItem('selectedDate', value);
}
};
Такой подход снижает количество операций записи и повышает стабильность при интенсивном взаимодействии с календарём.