recently I've trying to set up a cookie in order to validate a session in a Rails 3.2 app.
The cookie was supposed to expire at the beginning of the next day, this way I would force users to login again (mandatory)
First I changed my app's timezone to the one I was expecting to handle:
config.time_zone = 'Caracas'
After that I created the cookie as follows:
cookies[:remember_token] = {value: user.remember_token,
expires: 1.day.from_now.beginning_of_day}
The cookie gets created without any problem but the expire date is wrong. In Chromium the date is set to today a 19:30 PM (Although my machine timezone is set accordingly to the app).
The strange thing comes when I change the definition of the cookie to:
cookies[:remember_token] = {value: user.remember_token,
expires: 1.day.from_now}
If I set to cookie only to 1 day from today then the expire date is set properly to exactly 24 hours from now.
Any ideas why beginning_of_date is not setting the date correctly?
Thanks in advance
It is down to the order of execution. The time zone is applied after the beginning of day is calculated. E.g. I am in UTC timezone, and I can do the following in rails console:
irb(main):019:0> 1.day.from_now.in_time_zone(Time.zone).beginning_of_day
=> Thu, 01 Nov 2012 00:00:00 UTC +00:00
irb(main):020:0> 1.day.from_now.beginning_of_day.in_time_zone(Time.zone)
=> Thu, 01 Nov 2012 00:00:00 UTC +00:00
irb(main):021:0> Time.zone.now.tomorrow.beginning_of_day
=> Thu, 01 Nov 2012 00:00:00 UTC +00:00
irb(main):022:0> 1.day.from_now.beginning_of_day.in_time_zone('Caracas')
=> Wed, 31 Oct 2012 19:30:00 VET -04:30
irb(main):023:0> 1.day.from_now.in_time_zone('Caracas').beginning_of_day
=> Thu, 01 Nov 2012 00:00:00 VET -04:30
So if you change your cookie calculation to the following it should work:
cookies[:remember_token] = {value: user.remember_token,
expires: 1.day.from_now.in_time_zone(Time.zone).beginning_of_day}
Related
I’m new to writing Tests in Postman and below is what I’m not able to get through after spending couple of days researching. I’ll appreciate the expertise:
Following steps I have done so far. From POST request response I parse it to grab Epoch time and then convert that into human readable date time.
Response Body:
1604448930
Tue Nov 03 2020 18:15:30 GMT-0600 (Central Standard Time)
Below is what I have in Tests script:
jsonData = JSON.parse(responseBody)
x = jsonData[0].ScheduledAttempt.ScheduledDateTime;
epochScheduledDateTime = jsonData[0].ScheduledAttempt.ScheduledDateTime
console.log(epochScheduledDateTime)
Date = new Date ((epochScheduledDateTime) *1000);
console.log(Date)
Now how can I compare my human readable date to the expected min and max datetime.
For eg: Tue Nov 03 2020 18:15:30 GMT-0600 (Central Standard Time) is between
Tue Nov 03 2020 18:00:00 GMT-0600 (Central Standard Time) and
Tue Nov 03 2020 20:00:00 GMT-0600 (Central Standard Time).
Appreciate your guidance.
Thank You
Kp
you don't have to convert the epoch time to dateString, instead you can convert other datestrings and the epoch time to millisecond using the getTime() method of the Date.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime
Return Value: A Number, representing the number of milliseconds since
midnight January 1, 1970
Now you can use the chai expect method "within" to validate if the value is within the range specified
pm.test("Validate date to be within the expected date range", function () {
epochScheduledDateTime = 1604448930
valueGot = 1604448930 * 1000
pm.expect(valueGot).to.be.within((new Date("Tue Nov 03 2020 18:00:00 GMT-0600 (Central Standard Time)")).getTime(), (new Date("Tue Nov 03 2020 20:00:00 GMT-0600 (Central Standard Time)")).getTime());
})
Or compare dates:
pm.test("Validate date to be within the expected date range", function () {
pm.expect(new Date((epochScheduledDateTime) * 1000)).to.be.within((new Date("Tue Nov 2 2020 18:00:00 GMT-0600 (Central Standard Time)")), (new Date("Tue Nov 03 2020 20:00:00 GMT-0600 (Central Standard Time)")));
})
postman expect class is from chai and all chai bdd assertions are supported:
https://www.chaijs.com/api/bdd/
How do you convert a string with DOW and GMT information to timestamptz in Redshift?
Example: Mon Apr 01 2019 14:08:20 GMT-0400 (EDT)
Amazon Redshift is based on PostgreSQL. Therefore, with the use of TO_DATE function, along with timezone related clauses, we could try the following.
SELECT
TO_TIMESTAMP('Mon Apr 01 2019 14:08:20 GMT-0400 (EDT)', 'XXX Mon DD YYYY HH:MI:SS')
AT TIME ZONE REGEXP_REPLACE('Mon Apr 01 2019 14:08:20 GMT-0400 (EDT)', '^.*(...).$', '\\1');
This results in the following.
Unfortunately, it doesn't seem like we can do this conversion in one go because time zone related format flags are valid for TIMESTAMPTZ only.
How to select datetime column with timezone using ActiveRecord::Base.connection.execute()?
e.g
User.first.joined_at => Tue, 31 Jul 2018 05:00:34 MSK +03:00
but
ActiveRecord::Base.connection.execute("SELECT joined_at FROM users") => {"joined_at"=>"2018-07-31 02:00:34.684659"}
ActiveRecord::Base.connection.execute doesn't understand the database's types that well so you have to parse the strings yourself.
That timestamp should be in UTC as that's the Rails standard inside the database. You could go through Time.zone:
Time.zone = 'UTC' # Unless your application is already in UTC
t = Time.zone.parse('2018-07-31 02:00:34.684659').in_time_zone('Moscow')
# Tue, 31 Jul 2018 05:00:34 MSK +03:00
Or you could go through DateTime (which assumes UTC if the string doesn't have a timezone embedded in it):
DateTime.parse('2018-07-31 02:00:34.684659').in_time_zone('Moscow')
# Tue, 31 Jul 2018 05:00:34 MSK +03:00
I'm creating a new record with simple_form gem. There are 2 fields (start_date and end_date) which are for the date data.
Can someone help to understand how it is possible that the date saved is a day behind it was entered in the form?
#<Book:0x0000...
id: 16,
name: "My favorite book",
start_date: Thu, 30 Jun 2016 00:00:00 EEST +03:00,
end_date: Thu, 30 Jun 2016 00:00:00 EEST +03:00,
created_at: Thu, 30 Jun 2016 15:07:57 EEST +03:00,
updated_at: Thu, 30 Jun 2016 15:07:57 EEST +03:00>
Compare with:
INSERT INTO `books` (`name`, `start_date`, `end_date`, `created_at`, `updated_at`) VALUES ('My favorite book', '2016-06-29 21:00:00', '2016-06-29 21:00:00', '2016-06-30 12:07:57', '2016-06-30 12:07:57')
I'm trying to save June 30, but it stores June 29. How is it possible?
You're entering the date in EEST, and saving the date in UTC, so it will subtract 3 hours before saving it i.e. 2100 the previous day. If you convert the date back to EEST before you use it, you'll get the correct date.
Why it's doing this depends on your environment.
Your problem is related with rails timezones.
Did you setup your timezone in rails like this?
file: config.application.rb
config.time_zone = 'Eastern Time (US & Canada)'
config.active_record.default_timezone = :local
If you do so activerecord saves your data in your current timezone.
I've been working on parsing strings and I have a test case that has been causing problems for me. When parsing a date/time string with strptime, Daylight Savings Time is NOT accounted for. This is a bug as far as I can tell. I can't find any docs on this bug. Here is a test case in the Rails console. This is ruby 1.9.3-p215 and Rails 3.2.2.
1.9.3-p125 :049 > dt = DateTime.strptime("2012-04-15 10:00 Central Time (US & Canada)", "%Y-%m-%d %H:%M %Z")
=> Sun, 15 Apr 2012 10:00:00 -0600
1.9.3-p125 :050 > dt = DateTime.strptime("2012-04-15 10:00 Central Time (US & Canada)", "%Y-%m-%d %H:%M %Z").utc
=> Sun, 15 Apr 2012 16:00:00 +0000
1.9.3-p125 :051 > dt = DateTime.strptime("2012-04-15 10:00 Central Time (US & Canada)", "%Y-%m-%d %H:%M %Z").utc.in_time_zone("Central Time (US & Canada)")
=> Sun, 15 Apr 2012 11:00:00 CDT -05:00
As you can see, I have to convert to utc and then back to the timezone to get DST to be properly interpreted, but then the time is shifted one hour as well, so it's not what I parsed out of the string. Does someone have a workaround to this bug or a more robust way of parsing a date + time + timezone reliably into a DateTime object where daylight savings time is properly represented? Thank you.
Edit:
Ok, I found a workaround, although I'm not sure how robust it is.
Here is an example:
ActiveSupport::TimeZone["Central Time (US & Canada)"].parse "2012-04-15 10:00"
This parses the date/time string into the correct timezone. I'm not sure how robust the parse method is for handling this so I'd like to see if there is a better workaround, but this is my method so far.
This is a frustrating problem. The Rails method you're looking for is Time.zone.parse. First use DateTime.strptime to parse the string, then run it through Time.zone.parse to set the zone. Check out the following console output:
> Time.zone
=> (GMT-06:00) Central Time (US & Canada)
> input_string = "10/12/12 00:00"
> input_format = "%m/%d/%y %H:%M"
> date_with_wrong_zone = DateTime.strptime(input_string, input_format)
=> Fri, 12 Oct 2012 00:00:00 +0000
> correct_date = Time.zone.parse(date_with_wrong_zone.strftime('%Y-%m-%d %H:%M:%S'))
=> Fri, 12 Oct 2012 00:00:00 CDT -05:00
Notice that even though Time.zone's offset is -6 (CST), the end result's offset is -5 (CDT).
Ok, here is the best way I've found to handle this so far. I created a utility method in a lib file.
# Returns a DateTime object in the specified timezone
def self.parse_to_date(date_string, num_hours, timezone)
if timezone.is_a? String
timezone = ActiveSupport::TimeZone[timezone]
end
result = nil
#Chronic.time_class = timezone # Trying out chronic time zone support - so far it doesn't work
the_date = Chronic.parse date_string
if the_date
# Format the date into something that TimeZone can definitely parse
date_string = the_date.strftime("%Y-%m-%d")
result = timezone.parse(date_string) + num_hours.to_f.hours
end
result
end
Note that I add hours onto the time manually because Chronic.parse wasn't as robust as I liked in parsing times - it failed when no trailing zeros were added to a time, for example, as in 8:0 instead of 8:00.
I hope this is useful to someone. Parsing date/time/timzone strings into a valid date seems to be a very common thing, but I was unable to find any parsing code that incorporated all three together.