Часто при разработке ботов для Telegram требуется учитывать информацию о часовом поясе пользователя. К сожалению, получить её через Bot API невозможно, поэтому предусматривать в боте команду, с помощью которой пользователь сможет указать, какой часовой пояс он использует. И тут возникает вопрос, как лучше это сделать, чтобы пользователю было удобно. Если бот ориентирован только на российских пользователей, вопрос решается просто: выводим список всех часовых поясов России, пользователь выбирает нужный, и бот сохраняет выбор в базу данных.
Но как быть, если пользователи могут быть из других стран? Выводить огромный список из более чем сотни часовых поясов — крайне неудобно. Требовать от пользователя вручную написать название его часового пояса в формате Europe/Moscow или хотя бы MSK — тоже не самое лучшее решение. Можно предложить указать смещение в формате ±ЧЧ:ММ, но тогда нельзя будет учесть переход на летнее время.
В поисках более удобного решения я наткнулся на модули tzwhere и geopy. Первый позволяет определить часовой пояс для того или иного местоположения, заданного с помощью координат. Второй — получить эти самые координаты по названию города, причём позволяет это делать через Google Maps API, API Яндекс.Карт и ещё почти десяток сервисов. Я решил использовать Nominatim (это сервис Open Street Maps), так как он не требует получения tokenа, в отличие от Яндекс и Google, и при этом понимает названия городов и на английском языке, и на русском.
В итоге код определения часового пояса выглядит примерно так:
import geopy
from tzwhere import tzwhere
import datetime
import pytz
def get_timezone(bot,chat_id,city):
geo = geopy.geocoders.Nominatim(user_agent="SuperMon_Bot")
location = geo.geocode(city) # преобразуе
if location is None:
bot.send_message(chat_id,"Не удалось найти такой город. Попробуйте написать его название латиницей или указать более крупный город поблизости.")
else:
tzw = tzwhere.tzwhere()
timezone_str = tzw.tzNameAt(location.latitude,location.longitude) # получаем название часового пояса
tz = pytz.timezone(timezone_str)
tz_info = datetime.datetime.now(tz=tz).strftime("%z") # получаем смещение часового пояса
tz_info = tz_info[0:3]+":"+tz_info[3:] # приводим к формату ±ЧЧ:ММ
bot.send_message(chat_id,"Часовой пояс установлен в %s (%s от GMT)." % (timezone_str,tz_info))
# здесь должно быть сохранение выбранной строки в БД
return timezone_str
Приведение даты к нужному часовому поясу перед выводом пользователю делается либо с помощью метода tz.localize(dt) (для так называемых naive date, то есть не содержащих информацию о часовом поясе), либо с помощью метода dt.astimezone(tz), где dt — объект класса datetime, а tz — timezone.

- Перово, Москва, Россия
- me@4xpro.ru
- x4_pro
- XXXXPro
Новости сайта в Telegram
t.me/4x_proКомпьютерное
Часовой пояс в ботах для Telegram

Красивая транслитерация для URL с помощью AWS Lambda

Занимаясь SEO, столкнулся с тем, что во многих CMS URLы для страниц генерируются так: название прогоняется через транслитератор, потом небуквенные символы заменяются на _, и на этом все. С учетом того, что при наполнении сайта данные часто вставляются через буфер обмена с лишними пробелами, получаем ужасные адреса вида http://example.com/-ochen-horoshiy--tovar_-_kupite-оbyazatelno_. Глядя на это, я решил, что нужно создать транслитератор, который будет делать красивые URL. Такой транслитератор должен уметь следующее:
- делать регистр букв всегда нижним
- удалять все посторонние символы, кроме букв, цифр, тире и прочерков, а пробелы заменять на «-» (в соответствии с рекомендациями Google);
- обрезать пробелы по краям, а также несколько пробелов, идущих подряд;
- уметь обрезать URL по первой запятой (это полезно для многих магазинов, где после запятой часто идут второстепенные параметры товара, которые не требуется выносить в URL);
- уметь обрезать URL по границе слова так, чтобы не превышать указанную длину.
Встроить такое в какую-либо конкретную CMS несложно. Но хотелось сделать какое-то более универсальное решение — API, к которой можно было бы обращаться из любой CMS. И вот недавно я узнал о бессерверных вычислениях и платформе Lambda для Amazon Web Services. Я счел, что она для таких задач подходит идеально и решил попробовать её в деле.
"Подробнее о том, как создавался такой транслитератор и пример интеграции"
Время выполнения кода в PHP и Python

Иногда при написании скриптов требуется узнать, сколько времени скрипт выполняется. Для этого есть несколько способов. Во-первых, можно воспользоваться стандартной для Unix-систем утилитой time:
time script.sh
time python script.py
time php script.php
Она выдаст что-то вроде
real 0m0.012s
user 0m0.004s
sys 0m0.000s
Здесь нас интересует первое значение: real. Оно показывает, сколько реального времени заняло выполнение скрипта. User и sys показывают потраченное процессорное время в режиме пользователя и режиме ядра, которое, даже суммарно, может быть меньше реального из-за простоя и ожидания.
Но утилита time замеряет полное время выполнения, с учетом затрат на запуск интерпретатора, загрузку скрипта и т.п., что не всегда желательно.
Поэтому иногда бывает целесообразнее использовать средства самого языка программирования. В PHP для этого используется функция microtime:
$start_time = microtime(true); // true — получать данные в
// какой-то код
$time = microtime(true)-$start_time; // в переменой $time будет время в секундах,
// которое потрачено на выполнение кода
В Python все аналогично, только необходимо подключить модуль time:
import time
start_time = time.time()
# какой-то код
time = time.time()-start_time // время выполнения также будет в секундах
В JavaScript это выглядит чуть иначе — необходимо использовать объекты Date:
let start_time = new Date;
# какой-то код
time = (new Date -start_time)/1000 // разность между двумя объектами Date измеряется в милисекундах,
// поэтому делим ее на тысячу