Grails - Get next/previous TimeZone - grails

I'm working with a Grails application and I can't find a clear way to translate a date from one TimeZone to the next/previous TimeZone available (I will define what I consider the next/previous Timezone below).
The facts:
I'm working with date filters in a Grails Application so we can retrieve information based on those filters. The application supports TimeZone so the logged user can set his profile to a particular Timezone.
The dates of the filter are on UTC format and the information on the database is stored also on UTC.
The question:
The user logged has his profile on Timezone UTC+00.
There is a predefined date filter called "This Week", when a user clicks on it generate a period of dates corresponding to the current week in UTC so we can bring all the information on the database from the current week.
If we are on the current day (Thu 19 Nov 2015) the dates the filter will generate for "This Week" to look on the database would be:
Sun Nov 15 00:00:00 UTC 2015 to Sun Nov 22 23:59:59 UTC 2015
This is correct and will bring all the information on the database on that period.
Now, suppose the user doing this has set a Timezone UTC +01.
If we are on the current day (Thu 19 Nov 2015) the dates the filter will generate to look on the database would be the same period:
Sun Nov 15 00:00:00 UTC 2015 to Sun Nov 22 23:59:59 UTC 2015
But in this case I need to translate them to a correct TimeZone because the "This Week" for the current user won't be the same for a user on UTC +01 this is because for this user the date Sun Nov 15 00:00:00 would correspond to the date
Sun Nov 14 23:00:00 on the UTC time (since he/she is one hour ahead) and therefore when filter by "This Week" I should search on the database by the dates:
Sun Nov 14 23:00:00 UTC 2015 to Sun Nov 22 22:59:59 UTC 2015
The thing is I have created a method utcDateToUserTZ(date) to translate from an UTCDate to LocalTimeZone date but this would convert the UTC dates:
Sun Nov 15 00:00:00 UTC 2015 to Sun Nov 22 23:59:59 UTC 2015
into
Sun Nov 15 01:00:00 UTC 2015 to Sun Nov 23 00:59:59 UTC 2015
And that is not what I'm looking for. I need those dates to be translated to the previous TimeZone.
I hope no to be walking around with an issue that has a simpler solution, in which case I hope you can tell me if there exist something easier to solve this.
Thanks,
The method commented before is:
public DateTime utcDateToUserTZ(Date date) {
TimeZone profileTimeZone = getCurrentUserProfile().timeZone
DateTimeZone dateTimeZone = DateTimeZone.forTimeZone(profileTimeZone)
return new DateTime(date, dateTimeZone).withZone(dateTimeZone)
}

Related

How to compare UTC to DateTime.now in Ruby

I am trying to check if a time submitted by the user in a datetime_field in a form is less than the current time.
My current issue is that the submitted date is that exact date in UTC, is Mon, 13 Apr 2020 23:00:00 UTC +00:00, however, DateTime.now.utc is 2020-04-14 03:14:00.694513 UTC.
I would like to be able to compare just the dates and the times to compare them, regardless of the timezone they are in.

Sales Force UTC time conversion in rails

Time returned from salesforce is in this format 2017-07-14T12:02:23.000+0000 But I want to convert my saved time that is updated_At Wed, 04 Oct 2017 23:00:45 PDT -07:00
I tries to convert it in utc with time_var.utc but it returned 2017-10-05 06:00:45 UTC
How can i get the time in salesforce Format 2017-07-14T12:02:23.000+0000
time_in_utc = DateTime.parse product.updated_at.utc.to_s
last_update_time = time_in_utc.iso8601
updated_at = "Wed, 04 Oct 2017 23:00:45:032 PDT -07:00"
Time.parse(updated_at).utc.strftime("%Y-%m-%dT%T.%L%z")

In Ruby or Rails, what is the best way to convert Eastern Time to UTC?

I'm not referring to
myDateTime = DateTime.now
myDateTime.new_offset(Rational(0, 24))
or
Time.now.utc
What I have is a text date is given in Eastern Time.
I can convert that text date into a DateTime. Let's call it eastern_date_time.
Now, we have a variable containing an DateTime, but nothing knows it's eastern besides us. Converting it ourselves would be quite onerous. If the date in Daylight Savings Time (DST) (March 8 to November 1st this year), we'd have to add 4 hours to our eastern_date_time var to get UTC, and if the date is in Standard Time (ST) we'd have to add 5 hours to our eastern_date_time variable.
How can we specify that what we have is an Eastern DateTime, and then convert it to UTC... something that will determine if the date is in the DST/ST, and apply the 4 or 5 hours properly?
I want to convert any sort of date I get into UTC, for storage in my database.
EDIT:
Using `in_time_zone', I'm unable to convert my Eastern Text Time to UTC. How can I achieve that objective? For example...
text_time = "Nov 27, 2015 4:30 PM" #given as Eastern
myEasternDateTime = DateTime.parse text_time # => Fri, 27 Nov 2015 16:30:00 +0000
#now we need to specify that this myEasternDateTime is in fact eastern. However, it's our default UTC. If we use in_time_zone, it just converts the date at UTC to Eastern
myEasternDateTime.in_time_zone('Eastern Time (US & Canada)') # => Fri, 27 Nov 2015 11:30:00 EST -05:00
myEasternDateTime.utc # => Fri, 27 Nov 2015 16:30:00 +0000
That's not what we want. We have to specify that myEasterDateTime is in fact eastern... so that when we do a myEasterDateTime.utc on 16:30:00 we end up getting 20:30:00.
How can I accomplish this?
There was a time_in_zone method in the DateTime class:
now.time_in_zone('UTC')
It has since been renamed to in_time_zone:
DateTime.now.in_time_zone('US/Pacific')
=> Wed, 22 Apr 2015 12:36:33 PDT -07:00
The objects of Time class have a method called dst? which basically tells you whether or not DST is applicable or not. So you can basically identify whether DST/ST is applicable and decide which to add - 4 or 5.
e.g. Time.now.dst?
If it returns true, add 4, otherwise add 5.
I got it like this with the help of the time zone suggestions.
time_text_1 = "Apr 20, 2015 4:30PM" #Scraped as an Eastern Time, with no offset of -5:00 from UTC included
time_text_2 = "Nov 20, 2015 4:30PM" #Scraped as an Eastern Time, with no offset of -5:00 from UTC included
Time.zone = 'Eastern Time (US & Canada)'
my_time_1 = Time.zone.parse time_text_1 # Output: Mon, 20 Apr 2015 16:30:00 EDT -04:00
my_time_2 = Time.zone.parse time_text_2 # Output: Fri, 20 Nov 2015 16:30:00 EST -05:00
my_time_1.utc # Output: 2015-04-20 20:30:00 UTC
my_time_2.utc # Output: 2015-11-20 21:30:00 UTC
In the edited post, your string of time needs an offset from UTC.
EDIT III: Based on the comments (just having a string set to represent Eastern Time and needing to account for DST, etc.)
text_time = "Nov 27, 2015 4:30 PM"
the_offset = Time.zone_offset('EST') / (60*60)
eastern_time = DateTime.parse(text_time).change(offset: the_offset.to_s) # Fri, 27 Nov 2015 16:30:00 -0500
eastern_time.utc # Fri, 27 Nov 2015 21:30:00 +0000

Rails Records with times in different timestamps that occur on a date

Rails 4.2 and PostgreSQL 9.4.
I have events with starts_at and time_zone columns.
I'd like a SQL query to return all events that start, in their local time zone, on a specified date.
I.e. if an event starts at 11pm in Hawaii on Jan 24th:
t1 = ActiveSupport::TimeZone['Hawaii'].parse("2015-01-24 23:00:00")
=> Sat, 24 Jan 2015 23:00:00 HST -10:00
t1.in_time_zone('UTC')
=> Sun, 25 Jan 2015 09:00:00 UTC +00:00
And if an event starts at 1am in Hong Kong on Jan 24th:
t2 = ActiveSupport::TimeZone['Hong Kong'].parse("2015-01-24 01:00:00")
=> Sat, 24 Jan 2015 01:00:00 HKT +08:00
t2.in_time_zone('UTC')
=> Fri, 23 Jan 2015 17:00:00 UTC +00:00
The events occur on the 25th and 23rd of Jan in Rails' implicit UTC database zone, but both events occur on the 24th in their own time zone.
I'd like to write a SQL query akin to:
SELECT * FROM events WHERE (events.starts_at at time zone 'UTC' at time zone events.time_zone)::date = '2015-01-24';
(The initial conversion to UTC is required for a timestamp I believe)
However I get an error ERROR: time zone "Hawaii" not recognized
This is because PostgreSQL time zone names do not match with that of Rails (SELECT * FROM pg_timezone_names; for a list.)
Is there an alternative method where I can still do the query in SQL but not have this problem? I don't want to load the entire events set into Rails and process it there as it is very large and this is a frequent query.
As a small context as to why I need this query: I have a membership pass valid over a certain date range which gives you access to events which can occur in different time zones.
If there is no other way to do this, is there any tool that converts between the Rails names for time zones and that used by PostgreSQL so that I can save both the Rails zone and the PostgreSQL zone in the database record?
Using time zone abbreviations such as PDT instead (I don't even know if these are consistent between Rails and PostgreSQL either) doesn't deal with daylight savings time (which, granted, may not be an issue here but is not satisfactory).

How can I convert a Time from some timezone to UTC, taking into account Daylight Saving, in Ruby?

I have an app where different users are in different parts of the globe (I know their timezone), and they can enter dates and times, and I need to store everything in UTC on the DB.
Normally to instance my Time variable, I'm doing:
DateTime.new(date.year, date.month, date.day, hours, minutes, 0)
This is already in UTC, but without converting.
If I add a 7th parameter to that string with the time_zone (ie. "Melbourne"), then it will interpret it as a a date in Australia, and the resulting DateTime, when converted to UTC, is 10-ish hours behind, and that works.
However, that's not taking into account Daylight Saving.
What I need is to do exactly that (instance a DateTime from the components of a date/time), such that (in the case of Australia, for example), using the same hours/minutes for April 9th will give me a different offset when converted to UTC than if I used April 5th.
Any ideas?
Thanks!
Daniel
Have a look at tzinfo
irb(main):002:0> require 'tzinfo'
=> true
irb(main):003:0> tz = TZInfo::Timezone.get("Australia/Melbourne")
=> #<TZInfo::DataTimezone: Australia/Melbourne>
irb(main):004:0> tz.utc_to_local(Time.parse("2013-04-05 00:00:00"))
=> Fri Apr 05 11:00:00 UTC 2013
irb(main):005:0> tz.utc_to_local(Time.parse("2013-04-09 00:00:00"))
=> Tue Apr 09 10:00:00 UTC 2013
irb(main):015:0> tz.local_to_utc(Time.parse("2013-04-09 00:00:00"))
=> Mon Apr 08 14:00:00 UTC 2013
irb(main):016:0> tz.local_to_utc(Time.parse("2013-04-05 00:00:00"))
=> Thu Apr 04 13:00:00 UTC 2013

Resources