rails_param
rails_param copied to clipboard
Parsing the date/time parameter depends on the local zone setting in the operating system, not in the Rails application
Basic Info
- rails_param Version:
- Ruby Version: 3.2.2
- Rails Version: 7.1.1
Description
Using params! Time
gives incorrect results in case of parameter parsing without specifying time zone.
In this case the result depends on the local zone setting on the running computer/docker, but should be determined by the time zone setting in the application configuration.
Steps for reproduction
For the same application with time zone settings:
- run in docker with operation system time zone
- run in docker with operation system without time zone
Rails console example
Rails Time zone is set, container time zone - different (not set)
Applications are different in this example, but it is not a key.
[4] pry(main)> param = '01.01.2023 00:00:00'
=> "01.01.2023 00:00:00"
[5] pry(main)> options = { format: '%e.%m.%Y %H:%M:%S'}
=> {:format=>"%e.%m.%Y %H:%M:%S"}
[6] pry(main)> type = Time
=> Time
[7] pry(main)> type.strptime(param, options[:format])
=> 2023-01-01 00:00:00 +0000
[8] pry(main)> "01.01.2023 00:00:00".in_time_zone
=> Sun, 01 Jan 2023 00:00:00.000000000 MSK +03:00
[9] pry(main)> Time.parse(param)
=> 2023-01-01 00:00:00 +0000
[10] pry(main)> Problems::Application.config.time_zone
=> "Europe/Moscow"
Rails Time zone is set, container time zone - the same
>> param = '01/01/2023 00:00'
=> "01/01/2023 00:00"
>> option = { format: '%e.%m.%Y %H:%M:%S'}
=> {:format=>"%e.%m.%Y %H:%M:%S"}
>> type = Time
=> Time
>> options = { format: '%e.%m.%Y %H:%M:%S'}
=> {:format=>"%e.%m.%Y %H:%M:%S"}
>> param = '01.01.2023 00:00:00'
=> "01.01.2023 00:00:00"
>> type.strptime(param, options[:format])
=> 2023-01-01 00:00:00 +0300
>> Souz::Application.config.time_zone
=> "Europe/Moscow"
>> param.in_time_zone
=> Sun, 01 Jan 2023 00:00:00.000000000 MSK +03:00
Mmmh this is an interesting point.
IIRC config.time_zone
only affects the behaviour of Time.zone
, but that's not a class so you can't really pass it to param!
.
@ifellinaholeonce what do you think? I think the cleanest thing to do here is to leave Time
, Date
and DateTime
behaviour as-is and introduce a new ActiveSupport::TimeWithZone
param type that will internally coerce using Time.zone.parse
@iMacTia , if it helps in any way, I am currently using the following workaround.
param! :date_from, Time, format: '%e.%m.%Y %H:%M:%S',
transform: ->(date) { date.change(offset: Time.zone.formatted_offset) }
Then it works no matter what timezone is set in the OS, the timezone of the Rails application is used
Very interesting. I think leaving the behaviour of Time
, Date
and DateTime
and adding a new param type makes the most sense here.