Так как моя «профессиональная» жизнь связана с миром экономики, финансов, МСФО и бухучета, в свое время я написал скрипт, который шлет в почту напоминания вида «через неделю срок подачи декларации по налогу на прибыль».
И я понимаю: надо напомнить себе о том, что пора проводить ряд процедур для подготовки данных в части составления той или иной декларации или отчета.
В серии записей «Пишем телеграм-бота» я рассмотрю как сделать аналогичную напоминалку, но через функционал телеграма.
Бот будет уметь следующее:
- рассылать присоединившимся к нему пользователям напоминания о ближайших сроках предоставления конкретной декларации или отчета;
- получать на модерацию от пользователей новые сроки и описание по напоминанию.
В этом посте я напишу и протестирую «серверную» часть, где будет храниться информация по необходимым данным.
Даты и названия в гугл-таблицах
Стандартно создаю в гугл-таблицах пустую таблицу и из публичных источников беру информацию о сроках предоставления налоговых деклараций:
Тут пока все просто — столбец А формат «Дата», столбец B — текст
С табличной частью закончили. Единственное уточнение: в таких разработках я обрезаю лишние столбцы и/или строки там, где это можно. Все дело в быстродействии таблиц: чем короче таблица, тем быстрее она обрабатывается на стороне гугла.
Скрипт №1 — получение всего массива данных
Для тех, кто читает этот блог ничего нового в скрипте ниже не будет 🙂
// Google sheet
const ss = SpreadsheetApp.getActiveSpreadsheet()
const wsDb = ss.getSheetByName("DB")
// Получение всего массива с датами и данными
function getAllData() {
const dbArr = wsDb.getDataRange().getValues()
const dbArrWithDates = dbArr.map( row => [row[0].toLocaleString().split(',')[0], row[1]])
return dbArrWithDates;
}
Так как на листе «DB» только 2 столбца и хранятся только данные по дате и содержанию, можно получать массив через getDataRange: const dbArr = wsDb.getDataRange().getValues()
Сложность может вызвать следующая строчка:
const dbArrWithDates = dbArr.map( row => [row[0].toLocaleString().split(',')[0], row[1]])
если с map
все понятно то с .toLocaleString().split(',')
[0]
может быть немного сложнее. Все дело в том, что дата в массиве — это объект (если посмотреть на него через typeof(row[0])
)
и для простоты как сравнения, так и далее вывода в удобной и читаемой форме такую дату проще конвертировать в текстовый вид, а потом сплитить — метод split() разбивает строку на массив строк путём разделения строки указанной подстрокой, что в моем случае — запятая. В итоговом массиве нужен первый ([0]) элемент массива, представляющий из себя дату. Для сведения — второй ([1]) элемент массива это время.
Итоговый массив будет следующим:
Скрипт №2 — Дата для сравнения с датами массива
// Parameters
const LESSDAYS = 14 // За сколько дней ДО - предупреждать
// Получение даты для сравнения с датами в массиве
function getLessDays(){
const today = new Date()
today.setDate(today.getDate() + LESSDAYS)
const resultDays = today.toLocaleString().split(',')[0]
return resultDays;
}
Тут так же все просто:
- Получаю сегодняшнюю дату —
const today = new Date()
- Прибавляю к ней количество дней LESSDAYS. Это необходимо для дальнейшего сравнения: если новая дата равна дате из основного массива —
today.setDate(today.getDate() + LESSDAYS)
- Уже известный сплит —
const resultDays = today.toLocaleString().split(',')[0]
который возвращает новую дату в текстовом виде
Скрипт №3 — Фильтрация
// фильтрация общего массива на основании сравнения дат
function filteredDaysArr(){
const fullArr = getAllData()
const compareDays = getLessDays()
const filteredArr = fullArr.filter(row => row[0] == compareDays)
return filteredArr
}
Здесь я получаю результаты двух скриптов выше и фильтрую.
На выходе получаю отфильтрованный массив, который и буду отдавать телеграм-боту.
Небольшое уточнение — конечно же массив массивов. Его еще нужно будет преобразовать в текст в следствие ограничений телеграма на передачу данных. Ну и еще проверять длину массива, чтоб не передавать боту пустоту. Но об этом в следующих частях.
Здравствуйте, подскажите, пожалуйста, почему при выводе массива в телеграмм, дата становится на 1 день меньше?
К примеру дата: 11.02.2022, в телеграмм и в консоль, скрипт выводит 10.02.2022.
Добрый день.
Попробуйте потестировать даты независимо от скрипта
например
function testDates(){
const today = new Date()
console.log(today)
today.setDate(today.getDate() + 14)
console.log(today)
}
только что попробовал протестировать
Информация Wed Feb 16 2022 11:21:29 GMT+0300 (Moscow Standard Time)
вернул через 2 недели (+14 выше)
Информация Wed Mar 02 2022 11:21:29 GMT+0300 (Moscow Standard Time)
Вроде похоже, всё работает.
Еще как вариант — посмотреть к какому элементу массива обращаетесь. У меня идет обращение к первому, который [0]