Я отвечу на мой вопрос здесь, надеюсь, кто-то найдет его полезным
Все должны понимать, что дата или дата и время хранятся в поле json / jsonb как STRING , и вообще то, что случилось с моим кодом
user.token = {token_expires: Time.now.utc}
user.save
, заключается в том, что Rails неявно конвертирует Time.now.utc
в iso8601 , которые сохраняются в виде строки, и этопричина, почему, когда я делаю (в моей консоли)
user.token['token_expires']
, я получаю "2018-09-23T18: 21: 58.010Z" , который является форматом iso8601 моего предыдущего Time.now.utc
Не буду объяснять, почему Rails делает это преобразование, но насколько я понял, рекомендуется использовать формат ISO-8601 для хранения даты / даты и времени в базе данных, особенно для полей json / jsonbПотому что это облегчает работу с датой или при работе с API
Можете ли вы хранить другой формат, кроме ISO-8601? Да, вы можете , это зависит от ваших потребностей, например, я смог предотвратить Rails от неявного преобразования для меня, передав строку в моем коде вместо datetime, например:
user.token = {token_expires: Time.now.utc.to_s}
user.save
и сохраненное время (строка) будет выглядеть следующим образом: 2018-09-23 18:21:58 UTC
Возможно, вы захотите сохранить дату как время Unix,это зависит от вас!
Итак, вернемся к моей проблеме и запросу, который ничего не возвращает, мой запрос был похож на следующий:
User.where("""users.token ->> 'token_expires' <= :current_time""",
current_time: Time.now.utc).pluck(:id)
Здесь, в SQL-запросе Время.now.utc (current_time), с которым я сравниваю, становится примерно таким 2018-09-23 22:21:18.952113
, тогда как значения в базе данных (поле jsonb) имеют другой формат (iso8601), поэтому я ничего не получил в результате.
Таким образом, чтобы решить проблему, я должен был сохранить текущее время (Time.now.utc
) в виде строки, явно конвертировав его, используя .to_s Time.now.utc.to_s
, и запретить Rails конвертировать его в iso ...
Второе решение - конвертироватьформат iso datetime to timestamp в запросе SQL выглядит следующим образом:
User.where("""(users.token ->> 'token_expires')::timestamp <= :current_time""",
current_time: Time.now.utc).pluck(:id)
Вот и другие связанные вопросы, которые помогли мне прийти к такому выводу:
Является ли ISO8601 лучшим форматом даты для PostgreSQL jsonb, когда я хочу фильтровать по дате?
Даты JSONb: фактические даты внутри?
Преобразование метки времени UTC в ISO 8601 в рубине