Skip to content

Commit

Permalink
fix: date_time fields timezone (#2623)
Browse files Browse the repository at this point in the history
* fix: date_time fields timezone

* Update app/javascript/js/controllers/fields/date_field_controller.js

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* test

* UTC fix

* lint

* fix timezone check when nil

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
Paul-Bob and github-actions[bot] authored Mar 25, 2024
1 parent 432ef75 commit 5733e8e
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 6 deletions.
10 changes: 7 additions & 3 deletions app/javascript/js/controllers/fields/date_field_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,18 +204,22 @@ export default class extends Controller {
return
}

const timezonedDate = DateTime.fromISO(selectedDates[0].toISOString())
.setZone(this.displayTimezone, { keepLocalTime: true })
.setZone('UTC', { keepLocalTime: !this.relativeValue })

let value
switch (this.fieldTypeValue) {
case 'time':
// For time values, we should maintain the real value and format it to a time-friendly format.
value = DateTime.fromISO(selectedDates[0].toISOString()).setZone('UTC', { keepLocalTime: !this.relativeValue }).toFormat(RAW_TIME_FORMAT)
value = timezonedDate.toFormat(RAW_TIME_FORMAT)
break
case 'date':
value = DateTime.fromISO(selectedDates[0].toISOString()).setZone('UTC', { keepLocalTime: true }).toFormat(RAW_DATE_FORMAT)
value = timezonedDate.toFormat(RAW_DATE_FORMAT)
break
default:
case 'dateTime':
value = DateTime.fromISO(selectedDates[0].toISOString()).setZone('UTC', { keepLocalTime: !this.relativeValue }).toISO()
value = timezonedDate.toISO()
break
}

Expand Down
13 changes: 10 additions & 3 deletions lib/avo/fields/date_time_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,22 @@ def fill_field(model, key, value, params)
end

def utc_time(value)
if timezone.present?
ActiveSupport::TimeZone.new(timezone).local_to_utc(Time.parse(value))
time = Time.parse(value)

if timezone.present? && !time.utc?
ActiveSupport::TimeZone.new(timezone).local_to_utc(time)
else
value
end
end

def timezone
Avo::ExecutionContext.new(target: @timezone, record: resource.record, resource: resource, view: view).handle
timezone = Avo::ExecutionContext.new(target: @timezone, record: resource.record, resource: resource, view: view).handle

# Fix for https://github.com/moment/luxon/issues/1358#issuecomment-2017477897
return "Etc/UTC" if timezone&.downcase == "utc" && view.form?

timezone
end
end
end
Expand Down
128 changes: 128 additions & 0 deletions spec/system/avo/date_time_fields/timezone_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
require "rails_helper"

# Please use the reset_browser helpers before the first and after the last spec.
RSpec.describe "timezone", type: :system do
let!(:project) { create :project, started_at: Time.new(2024, 3, 25, 8, 23, 0, "UTC") } # "March 25, 2024 08:23:00 UTC"

subject(:text_input) { find '[data-field-id="started_at"] [data-controller="date-field"] input[type="text"]' }

after do
Avo::Resources::Project.restore_items_from_backup
end

describe "On Romania (EET) with CET timezone configured", tz: "Europe/Bucharest" do
before do
Avo::Resources::Project.with_temporary_items do
field :started_at, as: :date_time, timezone: "CET", time_24hr: true, format: "MMMM dd, y HH:mm:ss z"
end
end

it { reset_browser }

context "index" do
it "displays the date in CET tz" do
visit "/admin/resources/projects"

expect(index_field_value(id: :started_at, record_id: project.id)).to eq "March 25, 2024 09:23:00 CET"
end
end

context "show" do
it "displays the date in CET tz" do
visit "/admin/resources/projects/#{project.id}"

expect(show_field_value(id: :started_at)).to eq "March 25, 2024 09:23:00 CET"
end
end

context "edit" do
describe "when keeping the value" do
it "saves the valid date" do
visit "/admin/resources/projects/#{project.id}/edit"

expect(text_input.value).to eq "2024-03-25 09:23:00"

save

expect(show_field_value(id: :started_at)).to eq "March 25, 2024 09:23:00 CET"
end
end

describe "when changing the value" do
it "saves the valid date" do
visit "/admin/resources/projects/#{project.id}/edit"

expect(text_input.value).to eq "2024-03-25 09:23:00"

open_picker
set_picker_minute 24
set_picker_second 17

close_picker

save

expect(show_field_value(id: :started_at)).to eq "March 25, 2024 09:24:17 CET"
end
end
end
end

describe "On Romania (EET) with UTC timezone configured", tz: "Europe/Bucharest" do
before do
Avo::Resources::Project.with_temporary_items do
field :started_at, as: :date_time, timezone: "UTC", time_24hr: true, format: "MMMM dd, y HH:mm:ss z"
end
end

it { reset_browser }

context "index" do
it "displays the date in UTC tz" do
visit "/admin/resources/projects"

expect(index_field_value(id: :started_at, record_id: project.id)).to eq "March 25, 2024 08:23:00 UTC"
end
end

context "show" do
it "displays the date in UTC tz" do
visit "/admin/resources/projects/#{project.id}"

expect(show_field_value(id: :started_at)).to eq "March 25, 2024 08:23:00 UTC"
end
end

context "edit" do
describe "when keeping the value" do
it "saves the valid date" do
visit "/admin/resources/projects/#{project.id}/edit"

expect(text_input.value).to eq "2024-03-25 08:23:00"

save

expect(show_field_value(id: :started_at)).to eq "March 25, 2024 08:23:00 UTC"
end
end

describe "when changing the value" do
it "saves the valid date" do
visit "/admin/resources/projects/#{project.id}/edit"

expect(text_input.value).to eq "2024-03-25 08:23:00"

open_picker
set_picker_minute 24
set_picker_second 17

close_picker

save

expect(show_field_value(id: :started_at)).to eq "March 25, 2024 08:24:17 UTC"
end
end
end
end
end

0 comments on commit 5733e8e

Please sign in to comment.