jackc / tod

Time of day and shift types for Ruby
MIT License
435 stars 56 forks source link

undefined method 'mon' with I18n / Rails 6 #81

Closed KDGundermann closed 3 years ago

KDGundermann commented 3 years ago
Loading development environment (Rails 6.0.3.6)
3.0.0 :001 > I18n.l Tod::TimeOfDay.new(8, 30), format: :short
Traceback (most recent call last):
        1: from (irb):1:in `<main>'
NoMethodError (undefined method `mon' for #<Tod::TimeOfDay:0x0000563b1ef2cfd8 @hour=8, @minute=30, @second=0, @second_of_day=30600>)
Did you mean?  min
KDGundermann commented 3 years ago

https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/de.yml has for locale de:

time.formats.short: "%d. %B, %H:%M Uhr"

and https://github.com/ruby-i18n/i18n/blob/df7062f5903146ea231a18260ddf1f5083580e34/lib/i18n/backend/base.rb#L260

format.to_s.gsub(/%(|\^)[aAbBpP]/) do |match|
    case match
        ...
        when '%b' then I18n.t!(:"date.abbr_month_names",                :locale => locale, :format => format)[object.mon]
        when '%^b' then I18n.t!(:"date.abbr_month_names",               :locale => locale, :format => format)[object.mon].upcase
        when '%B' then I18n.t!(:"date.month_names",                     :locale => locale, :format => format)[object.mon]
jackc commented 3 years ago

There is no built-in support for integrating with Rails I18N.

morgler commented 2 years ago

Did you solve this? Because the README says that tod would have support for i18n.

Particularly the line from the README documentation does not work (it causes the above mentioned error):

Or i18n in a Rails ERB view. <%= l Tod::TimeOfDay.new(8, 30), format: :short %>

How can we work around this issue?

The most straight forward solution would be to edit/override the :short format in your yml. The rails-i18n gem defines this with a month (hence calling the mon method), but tod has no concept of month. So either use a different format or change :short like so:

de:
  time:
    formats:
      short: "%H:%M Uhr"
morgler commented 2 years ago

It seems that tod is not replying to the standard ruby Time.mon method:

https://www.geeksforgeeks.org/ruby-time-mon-function/

So I think the fix could be to add a mon method to tod that returns any arbitrary value (like 1) – what do you think?

It doesn't make much sense for a tod to respond to date methods like mon or wday, but in order to use a tod in place of a regular ruby Time it needs to somehow respond to these methods. I think the question is: should a tod be able to be used like a ruby Time or not? Ruby time is definitely a different concept ("point in time") from tod ("time of day") – so it doesn't make sense. But the README of tod suggests that a tod can be used like a Time (and even be stored as a Time type in the DB). So what to make of it?