rails_param icon indicating copy to clipboard operation
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

Open sergey-arkhipov opened this issue 1 year ago • 3 comments

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

sergey-arkhipov avatar Oct 29 '23 22:10 sergey-arkhipov

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 avatar Oct 30 '23 10:10 iMacTia

@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

sergey-arkhipov avatar Oct 30 '23 11:10 sergey-arkhipov

Very interesting. I think leaving the behaviour of Time, Date and DateTime and adding a new param type makes the most sense here.

ifellinaholeonce avatar Oct 31 '23 19:10 ifellinaholeonce