store tzinfo time zones

This commit is contained in:
ulferts
2021-10-04 17:08:15 +02:00
parent 39c8ad59b4
commit 71574a738b
3 changed files with 50 additions and 28 deletions
+21 -1
View File
@@ -48,8 +48,28 @@ module Settings
##
# Returns time zone (label, value) tuples to be used for a select field.
# As we only store tzinfo compatible data we only provide options, for which the
# values can later on be retrieved unambiguously. This is not always the case
# for values in ActiveSupport::TimeZone since multiple AS zones map to single tzinfo zones.
def time_zone_entries
time_zones.map { |tz| [tz.to_s, tz.name] }
time_zones
.group_by { |tz| tz.tzinfo.name }
.values
.map do |zones|
tz = namesake_time_zone(zones)
[tz.to_s, tz.tzinfo.canonical_identifier]
end
end
# If there are multiple AS::TimeZones for a single TZInfo::Timezone, we
# one return the one that is the namesake.
def namesake_time_zone(time_zones)
if time_zones.length == 1
time_zones.first
else
time_zones.detect { |tz| tz.tzinfo.name.include?(tz.name.gsub(' ', '_')) }
end
end
end
end
@@ -54,7 +54,10 @@ module UserPreferences
protected
def time_zone_correctness
errors.add(:time_zone, :inclusion) if model.time_zone.present? && model.canonical_time_zone.nil?
if model.time_zone.present? &&
ActiveSupport::TimeZone[model.time_zone]&.tzinfo&.canonical_identifier != model.time_zone
errors.add(:time_zone, :inclusion)
end
end
##
@@ -50,8 +50,9 @@ describe UserPreferences::UpdateContract do
enabled: true,
times: %w[08:00:00+00:00 12:00:00+00:00]
},
time_zone: 'Brasilia',
warn_on_leaving_unsaved: true
time_zone: 'America/Sao_Paulo',
warn_on_leaving_unsaved: true,
workdays: [1, 2, 4, 6]
}
end
let(:contract) { described_class.new(user_preference, current_user) }
@@ -237,36 +238,34 @@ describe UserPreferences::UpdateContract do
it_behaves_like 'contract is invalid', time_zone: :inclusion
end
describe 'workdays' do
context 'with valid entries' do
let(:settings) do
{
workdays: [1, 2, 4, 6]
}
end
it_behaves_like 'contract is valid'
context 'with a non tzinfo time_zone' do
let(:settings) do
{
time_zone: 'Brasilia'
}
end
context 'with duplicate entries' do
let(:settings) do
{
workdays: [1, 1]
}
end
it_behaves_like 'contract is invalid', time_zone: :inclusion
end
it_behaves_like 'contract is invalid', workdays: :no_duplicates
context 'with duplicate workday entries' do
let(:settings) do
{
workdays: [1, 1]
}
end
context 'with non-iso entries' do
let(:settings) do
{
workdays: [nil, 'foo', :bar, 21345, 2.0]
}
end
it_behaves_like 'contract is invalid', workdays: :no_duplicates
end
it_behaves_like 'contract is invalid', workdays: %i[invalid type_mismatch_nested
type_mismatch_nested type_mismatch_nested]
context 'with non-iso workday entries' do
let(:settings) do
{
workdays: [nil, 'foo', :bar, 21345, 2.0]
}
end
it_behaves_like 'contract is invalid', workdays: %i[invalid type_mismatch_nested
type_mismatch_nested type_mismatch_nested]
end
end