time is not saved in UTC time - ruby-on-rails-3

Using Rails 3 and PostgreSQL 8, I have a fuel_date column with data type "timestamp without time zone". A user selects a date and time from dropdown menu in their local time and when it's submitted to server, it should be saved as UTC time:
def create_fuel_service
attributes = {}
fuel_service_hash = params[:fuel_service]
datetime = DateTime.new(fuel_service_hash["fuel_date(1i)"].to_i, fuel_service_hash["fuel_date(2i)"].to_i,
fuel_service_hash["fuel_date(3i)"].to_i, fuel_service_hash["fuel_date(4i)"].to_i,
fuel_service_hash["fuel_date(5i)"].to_i).in_time_zone(current_user.time_zone).utc
attributes[:fuel_date] = datetime
fuel_service = FuelService.new(attributes)
if fuel_service.save
...
However, the record is saved as localtime, not UTC time, even though the created_at and updated_at fields are saved as UTC time:
http://s22.postimg.org/caho7v6c1/utctime_issue.png
How can I convert the fuel_date field to UTC time before saving? Using the UTC time method of DateTime does nothing.

What ended up working was using Time.new rather than DateTime.new:
datetime = Time.new(fuel_service_hash["fuel_date(1i)"].to_i, fuel_service_hash["fuel_date(2i)"].to_i,
fuel_service_hash["fuel_date(3i)"].to_i, fuel_service_hash["fuel_date(4i)"].to_i,
fuel_service_hash["fuel_date(5i)"].to_i)

Related

Reading and Writing UTC to TIMESTAMP in Postgresql

I have a Java application that inserts data into a database using prepared statements. In the preparedStamement date is set in UTC format.
preparedStatement.setDate(index, new java.sql.Date(date.getTime()), UTC);
I want to be sure that when read and write operations execute on the table, the response should ALWAYS be in UTC format. At the below query, when the data is read it will be converted to the client's timezone. I don't want TIME_COLUMN to be converted to any time zone. It should remain in the UTC time zone. How can I define TIME_COLUMN in that way?
Notes: I cannot edit the DB timezone. I cannot edit select queries using At time zone.
"TIME_COLUMN" TIMESTAMPTZ default (now() at time zone 'utc'),
You could set the timezone of your RDBMS to UTC, see https://medium.com/building-the-system/how-to-store-dates-and-times-in-postgresql-269bda8d6403
When that's done, whatever dates you store, they will be in UTC. Converting from UTC into something else can be done either in queries, like
select created_at at time zone 'utc' at time zone 'america/los_angeles'
from users;
Taken from https://popsql.com/learn-sql/postgresql/how-to-convert-utc-to-local-time-zone-in-postgresql
Or, you can convert the timezone at application level.

Get UTC date and time with time zone offset

I need a SQL Server function (or composition) to record the UTC date and time with the timezone offset into one of my columns of type datetimeoffset(7).
I observe that the SYSUTCDATETIME function gets the UTC date and time into a datetime2(7) data type and therefore that doesn't store the offset.
So, my question is: is there a composition of functions that will yield a datetimeoffset(7) value with the UTC date time along with the time offset (0:00)?

convert local time to utc and add to utc datetime moment

I have a user input where the user enters year, month and day and I create a date object
let userDate = new Date(year, month, day)
and then from a user input where the user enters minutes and hours (into variables minutes and hours)
I need to convert this date and time into UTC timestamp, using moment and I'm not sure about it. Can I just do
let utcTimestamp = moment.utc(date.toISOString()).hour(hours).minutes(minutes);
For example: if a user enters a date of 13-Mar-2018 and time of 8:45 AM (in GMT timezone), then I could use the above line of code to get UTC timestamp as I can directly add hours and minutes to the date
if a user enters a date of 13-Aug-2018 and time 8:45 (which is GMT +1, due to daylight savings time change) then with above line I might be creating a wrong date.
... I create a date object
let userDate = new Date(year, month, day)
Be careful here, you need to subtract 1 from the month, as they are numbered 0-11 by the Date instead of the usual 1-12.
and then from a user input where the user enters minutes and hours (into variables minutes and hours)
I need to convert this date and time into UTC timestamp, using moment ...
You don't need Moment for this. Just call .toISOString() on the Date object. It implicitly converts to UTC before generating the string.
var utcString = new Date(year, month-1, day, hours, minutes).toISOString();
... Can I just do
let utcTimestamp = moment.utc(date.toISOString()).hour(hours).minutes(minutes);
No, that doesn't make sense. That would only work if the date was entered in local time but the time was entered in UTC. Such a difference in behavior would surely be confusing to your user - especially if the UTC date was different than the local date.
... if a user enters a date of 13-Aug-2018 and time 8:45 (which is GMT +1, due to daylight savings time change) then with above line I might be creating a wrong date.
The conversion from local time to UTC will automatically take into account any daylight saving adjustment that is being observed by the local time zone. You do not need to do any additional adjustment on your own.
This is a snippet i used to convert an outlook calendar event from UTC to local time. The same Technique could be used for other scenarios.
//Get the users timezone
let timeZone = item.originalStartTimeZone;
//Get the start datetime in UTC time
let timeStart = item.start.dateTime;
//Calculate the negative offset.
let offset = - timeStart.localeCompare(timeZone);
//Add the calculated offset to the UTC start time
let localStartTime = addHours(timeStart, offset);

Display UTC Datetime to user defined timezone

I have dates in UTC in database, and I have the user timezone in their preferences table.
I have an extension method to convert from UTC to user time:
public static DateTime ToClientTime(this DateTime dt)
{
TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("SA Pacific Standard Time"); //Hardcoded timezone
return TimeZoneInfo.ConvertTimeFromUtc(dt, cstZone);
}
As you can see in the code below, for now it has a hardcoded time zone name, and I should pass by parameter that value (passing the user timezone).
In CurrentThread I set the user culture, so all code in this request behaves in that culture (date formats, resources, number formats). There is a way to store the user's timezone in a global object like CurrentThread or something like that?
What I'm trying to accomplish is avoid passing the time zone to the above extension method, and instead get the timezone from a global object like CurrentThread. The extension method will be called from Controller code and also from Views.
You have a base time like UTC, right? Not you have a user specified time zone in data base. So now you can either add or subtract from the UTC time zone depending on the need.
Probably addition can provide a simple solution.
Example:
Name ----------TimeZone
------------------------
Nick ------- UTC - 6
Hary ------- UTC + 1
So, if the current UTC time is 7 PM or 18:00 then
Nick = 18-6 = 12 / 12 PM
Harry = 18+1 = 19 / 8PM

Still confused about Timezone and conversions

I collect user time zone and a time they want something delivered in that time zone.
My application is set to use Bangkok Time.
application.rb
config.time_zone = 'Bangkok'
I want to store the time the user has entered relative to my timezone.
So say for example the user selects the following:
time = "6:00"
timezone = "(GMT-10:00) Hawaii"
I want to convert this time to the time of my application and save it in the database.
How can I convert from 6AM Hawaii time zone to what time this is in Bangkok?
Let us use your example to demonstrate:
config.time_zone = 'Bangkok'
time = "6:00"
timezone = "Hawaii"
The first thing you need to do is set the timezone of your app to the timezone that the user picked:
Time.zone = "Hawaii"
You then use the this new time zone to parse time time:
hawaii_time = Time.zone.parse("6:00")
If we now print out hawaii_time we get something similar to (we have HST -10:00 which means it is correct):
Mon, 15 Aug 2011 06:00:00 HST -10:00
You now use the rails in_time_zone method to convert to your app's timezone:
local_time = hawaii_time.in_time_zone(Rails.configuration.time_zone)
If we print out local_time we'll get something similar to (we have ICT +07:00 which is correct for Bangkok):
Mon, 15 Aug 2011 23:00:00 ICT +07:00
We can now reset the timezone of our app back to its original value:
Time.zone = Rails.configuration.time_zone