Search code examples
ruby-on-railsrubycoffeescripthamljquery-ui-datepicker

How to convert time to UTC before sending to server in Ruby on Rails application using jQuery Datepicker


I recently took over a fully functioning project written in Ruby on Rails. A bug was reported for which I am trying to solve and not having much success.

This is the CoffeeScript code that is called in the Haml code:

$('#report-datetime-picker').daterangepicker({
    timePicker: true,
    timePicker12Hour: false,
    timePickerIncrement: 5,
    format: 'YYYY-MM-DD HH:mm'
  }, (start, end) ->
    # assign human readable string to input box
    # unix times are the real values sent to server.  datetime-text-field is just user frontend
    $('#datetime-start').val(start.unix())
    $('#datetime-end').val(end.unix())
    $('#datetime-text-field').val(start.format('YYYY-MM-DD HH:mm') + " - " + end.format('YYYY-MM-DD HH:mm'))
  )

and:

                %label#datetime-label{ for: 'datetime-text-field' } Date/Time Range
                .form-group
                    .input-group.date#report-datetime-picker
                        %span.input-group-addon.add-on
                            %i.fa.fa-calendar

                        %input.form-control#datetime-text-field{ type: 'text', value: @time_format }

                %input#datetime-start{ hidden: true, name: 'startTime', text: 'text', value: (@start_time.to_i rescue nil) }
                %input#datetime-end{ hidden: true, name: 'endTime', text: 'text', value: (@end_time.to_i rescue nil) }

                %button.btn{ type: 'submit' } Submit

The issue is that when a user selects a date range, it is being converted to its UTC equivalent with regards to the user's current system time.

For example, if a user in the Eastern timezone wants to pull a monthly report and thus selects "4/1/2020 0:00 - 4/30/2020 23:59", it is instead sending to the server 4/1/2020 04:00 - 5/1/2020 03:59, causing the monthly report to miss the first four hours of activity, and incorrectly including the first four hours of the following month's activity. Month relations are not able to be used, as the time ranges are not necessarily a monthly report even though that is the most common use-case.

I checked application.rb and config.time_zone = 'UTC'. I also scoured the rest of the code and all timezone references are in UTC.

I also confirmed that if a user in the Eastern timezone selects "4/1/2020 00:00" in the date picker, the time that is actually stored in the start time is 4/1/2020 04:00, not 4/1/2020 00:00.


Solution

  • As the query works fine but is displaying it incorrectly,try converting to a normal JS date object rather than the .unix() method, then convert to UTC on the server

    $('#datetime-start').val(start.toDate())
    $('#datetime-end').val(end.toDate())
    

    When the form is submitted, and the values are sent to the server, they should contain the timezone info (eg. Wednesday, April 8, 2020 11:11:50 AM GMT+01:00 DST)

    If you parse this into a date object server side you can then convert it to a Time object with Time.parse and use .utc() to convert it from the given timezone to UTC.