Il y avait une demande pour enregistrer l'heure d'événements tels que les réunions en tenant compte de tous les fuseaux horaires.
Par exemple Meeting1 aura lieu à Tokyo à partir de 11h00. Meeting2 aura lieu à partir de 10h00 UTC.
Je veux exprimer quelque chose comme.
--Fixez le fuseau horaire par défaut du serveur API Rails. --Enregistrer le fuseau horaire dans la base de données
Tout d'abord, Rails a plusieurs fuseaux horaires à prendre en compte.
https://qiita.com/joker1007/items/2c277cca5bd50e4cce5e
Cette fois, pour éviter toute confusion, j'ai défini tous les fuseaux horaires ci-dessous sur UTC.
Enregistrez la variable de référence qui modifie le fuseau horaire. Le fuseau horaire étant modifié via ActiveSupport, vous pouvez écrire la validation suivante afin que la valeur valide soit enregistrée.
# tz :string
class Meeting < ApplicationRecord
validates :tz, inclusion: { in: ActiveSupport::TimeZone::MAPPING.values }, presence: true
end
Lorsque l'API renvoie une valeur, nous mettons dans une logique qui modifie dynamiquement le fuseau horaire et renvoie l'heure. Dans ce cas, je l'ai incorporé dans Serialzer. Comme cette logique est liée à l'affichage, nous avons donc décidé de la placer dans un calque proche de View.
# tz :string
class Meeting < ApplicationRecord
~réduction~
def timezone
ActiveSupport::TimeZone.new(tz)
end
def use_timezone
Time.use_zone(timezone) do
yield
end
end
end
class MeetingSerializer
attribute :start_time do |record|
record.use_timezone do
record.start_time
end
end
end
Enregistrer est avec les informations de fuseau horaire, si vous passez une chaîne, ActiveRecord le fera bien.
# actieve_le fuseau horaire de l'enregistrement est UTC
[47] pry(main)> meeting
=> #<Meeting:0x00007ff2c7ad4618
id: "162b1ed7-5502-42f8-8bed-592d2dae7db1",
start_at: Mon, 05 Oct 2020 16:00:00 UTC +00:00,
created_at: Tue, 06 Oct 2020 06:28:39 UTC +00:00,
updated_at: Thu, 08 Oct 2020 02:11:54 UTC +00:00>
[48] pry(main)> meeting.start_at="2020-10-06T01:00:00+0900"
=> "2020-10-06T01:00:00+0900"
[49] pry(main)> meeting.start_at
=> Mon, 05 Oct 2020 16:00:00 UTC +00:00
J'ai créé un module de préoccupation de contrôleur comme celui ci-dessous et j'ai effectué une validation avec before_action.
module ValidateTimeFormat
class TimeFormatError < StandardError
end
extend ActiveSupport::Concern
included do
rescue_from ValidateTimeFormat::TimeFormatError, with: :render_time_format_error
end
TIME_FORMAT = '%FT%T%z'
def render_time_format_error(msg)
render json: { message: msg }, status: :bad_request
end
def validate_time_format(time_str)
DateTime.strptime(time_str, TIME_FORMAT).zone
rescue Date::Error
raise ValidateTimeFormat::TimeFormatError, :time_format_is_invalid
end
end
Rails avait une image qu'il y a de nombreux points à considérer dans le système de temps. Avec cette implémentation, j'ai bien compris ()
https://twitter.com/yoshixj
Recommended Posts