In my database I have a datetime stored as text as:
2013-12-14T02:35:00-07:00
I want to determine if this time is before the current time. I can do this in Ruby as follows:
if DateTime.parse('2013-12-14T02:35:00-07:00') < Time.now.to_datetime
#do something
end
This provides the expected results. However, I am accessing my database like this:
#list = Alert.where("time_alert < ? ", Time.now.to_datetime)
which is not working as time_alert is being stored as text and the comparison is off. I am not sure how to parse time_alert into a DateTime object like in the condition.
Related
Is there a way with active record sql server adapter to query a hash field? I have a field called properties that is stored like this:
--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
summary: There is a problem
optional_information: Help!!
location: '28288'
reported_phone: "(555) 555-0352"
reported_email: person#email.com
affected_person_id: '1234'
affected_person_name: 'Tester'
affected_person_phone: '(555) 555-0352'
affected_person_email: person#email.com
I want to set up a query so that I pass a param through called filter and query either the summary field of the hash. Is this possible?
Trying to do somethings like this:
#requests = current_user.requests.where("properties->>'summary' = ?", '%#{params[:filter]}%') if params[:filter].present?
UPDATE: Per the advice below I changed the model to serialize the field as JSON. I also ran a migration to change the DB field type to JSON. Here is what the field looks like now. Still trying to figure out how to access and query the individual values.
{"summary":"Need bed raised","optional_information":"too low","location":"26679","reported_phone":"(555) 334-1324","reported_email":"mail#mail.com","affected_person_id":"1231232","affected_person_name":"testuserJ ","affected_person_phone":"(555) 334-1324","affected_person_email":"mail#mail.com"}
Python3.7 :: Eve:
Looking for a way to format datetime for a domain field instead of setting a global datetime format?
I am trying to store yyyy-mm-dd format but I don't want to change how the _created and _update work. Am I better off just storing the string and handling date conversion as part of the front end render?
--edit--
Would it be expensive to use a validator like so?
import datetime
from dateutil.parser import parse
from eve.io.mongo import Validator
class MyValidator(Validator):
"""
Extend / override the built-in validation rules
"""
def _validate_is_yyyymmdd(self, is_yyyymmdd, field, value):
"""datetime format yyyy-mm-dd"""
print(is_yyyymmdd, field, value)
print(datetime.datetime.strptime(value, r'%Y-%m-%d'))
print(is_yyyymmdd and datetime.datetime.strptime(value, r'%Y-%m-%d'))
try:
if is_yyyymmdd and datetime.datetime.strptime(value, r'%Y-%m-%d'):
return
except:
self._error(field, "Value is not valid yyyy-mm-dd")
volumes.py
volumes = {
'schema':{
'record_date':{
'type':'string',
'is_yyyymmdd':True,
},
'volume_gallons':{'type':'float'},
}
SOLVED - update
DATE_FORMAT = r"%Y-%m-%dT%H:%M:%S.%f%Z%z"
Using the new date format the payload can be submitted with a timezone adjustment which is then stored in mongo as UTC.
{
"record_date":"2019-04-06T15:49:12.012UTC+0500",
"group":"horizontal",
"program_year":2016
}
python script to help convert to utc from a given time
from datetime import datetime
from dateutil import tz
from dateutil.parser import parse
def main():
"""
modified solution found here: https://stackoverflow.com/questions/4770297/convert-utc-datetime-string-to-local-datetime
"""
# set the time zones to convert from and to
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
from_zone = tz.gettz('America/Denver')
to_zone = tz.tzutc()
# This is the format SQL Server outputs date time
datetime_str = "2019-03-21 02:37:21"
# local = datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S')
local = parse(datetime_str)
# Tell the datetime object that it's in local time zone since
# datetime objects are 'naive' by default
local = local.replace(tzinfo=from_zone)
# Convert time zone
utc = local.astimezone(to_zone)
print(utc, local)
if __name__ == "__main__":
main()
It's generally a good idea to leave the database field in its most agnostic format.
Create a method to handle the conversion details.
If you're annoyed by the prospect of typing out the full date/time conversion every time you need to have a date output, you could create a method in your object which handles the conversion in the way you like.
That way, you can name it something easy to remember and save yourself the hassle of remembering the exact notation of the date / time format function.
You might even create a super-class for your objects, and add the method there, so that it would be inherited by all the objects which you'd like to have this behavior available.
So if you have BlogObject class as a super-class, and BlogPost inherits from BlogObject, and you're accessing a standard field which exists in all those objects, such as Date Created or Date Modified
class BlogObject(BaseClassName):
def pretty_create_dt():
self.beatify_date(self.update_dt)
def beautify_date(date):
#[your format code]
#then have the other class(es) inherit the method:
class BlogPost(BlogObject):
def get_xmas_date_before(days_before_xmas):
date_x_before_christmas = self.beautify_date(self.xmas_dt - days_before_xmas)
#pseudo-code-ish, just to get the point across
That way, when you call a function from your template, it's already formatted by the Model or Controller. You should avoid doing this sort of thing in the View, because it's bad MVC practice, especially for something you plan to utilize application-wide.
The reason that this is the generally-accepted pattern is that
it reduces repetitive code processing which is prone to human error
it is less work-intensive for future development
It maintains the "separation on duty" inherent in MVC framework
For example, if date format policy were to change, perhaps due to internationalization, then you'd want a solution which could be modified in one location (Model or Controller super-class), rather than in 1,000 view instances
I do have a postgres DB which contains a timestamp. This timestamp follow the ISO standard and looks like:
2017-08-28 20:14:45.684926+00
I have used ActiveRecord to access the DB from Ruby/Sinatra environment but the ts returned is ISO8601.
Is there a way to force the formatting to ISO and not ISO8601 ?
I would like to avoid parsing the data once received.
Right now, I am using the command:
class ApiResponse < ActiveRecord::Base
class << self
def send_query(user, params)
limit = params.include?('limit') ? params['limit'] : 50
where_params = {
userid: user,
allowed_intent: true
}
ApiResponse.select([:id, :ts, :userid, :intent, :response])
.where(where_params)
.order(ts: :desc)
.limit(limit).to_a
end
end
The ApiResponse class is used to access the DB through ActiveRecord and it works fine. but the format is not correct. it shows :
2017-08-29T05:58:44.488Z
instead of something like
2017-08-28 20:14:45.684926+00
This format ISO is the one in the db
Any idea how to get the timestamp ts correctly formated as I expect inside the ActiveRecord call?
I think there are some misunderstandings here:
Postgres uses ISO 8601 for output (the so called ISO, they are not different standards) https://www.postgresql.org/docs/9.6/static/datatype-datetime.html
ActiveRecord, I assume, returns an instance of DateTime class or something similar, and not a string in that format.
What you see is only a format used for displaying; you can use strftime to display the data in another format.
I have a rails view where the user is presented with a dropdown displaying the hours '00:00', '01:00' etc.
Once the user has selected this hour, then it is stored in the model with some other fields.
My application is working in timezone UTC+2 (I have set config.time_zone = 'Jerusalem').
At what stage to I related to timezones when handling this time on its path from the view to the model? If I use e.g. DateTime.strptime("10:00", "%H:%M").in_time_zone(Time.zone), then I get a time at '12:00' - while what I really would like is for the database to store in UTF (which should be 08:00 while the rest of the site works with local time.
You can use TZInfo ruby library http://tzinfo.rubyforge.org and convert your time with following method
def local_to_utc(date, time_zone)
begin
unless time_zone.nil?
tz = TZInfo::Timezone.get(time_zone)
return tz.local_to_utc(date)
end
rescue
return nil
end
end
I have a problem with timezones and a postgresql db (Rails 3.0.4, PostgreSQL 9.0). I'm using a custom scope, in which I append some conditions, do joins etc.pp.
The problem is, that Rails don't convert the times to my local timezone.
Here is the code of the scope:
scope :with_activities_within_range_in_week, lambda{ |latMin, lngMin, latMax, lngMax, date|
select("date_trunc('day', activities.starting_at) as date,
count(activities.id) as value
") \
.within(latMin, lngMin, latMax, lngMax) \
.joins(:activities) \
.merge(Activity.in_week(date)) \
.group("date") \
.order("date")
}
The within method checks for ranges, the Activity.in_week scope returns this:
where("activities.starting_at >= ? AND activities.starting_at < ?", start, stop)
And in the select statement, I want to trunc the starting_at field to day.
I'm getting the following output for the date field:
2011-04-07 18:48:32
2011-04-02 14:07:20
2011-04-02 14:06:49
Unfortunately it doesn't include the timezone. When I try to access my model through the "normal" Rails functions, it works:
puts Activity.first.starting_at
-> 2011-04-15 06:47:55 +0200
What I'm doing wrong? Hope someone can help!
thx,
tux
Your database is storing your timestamps in UTC (as it should). ActiveRecord is making timezone adjustments when it knows that it has a timestamp; so, when you say this:
puts Activity.first.starting_at
AR knows that starting_at is a timestamp so it instantiates the timestamp as an ActiveSupport::TimeWithZone instance and that class applies the timezone adjustment. But, when you say this:
select("date_trunc('day', activities.starting_at) as date ...
AR isn't going to parse the SQL to figure out that date_trunc will return a timestamp, AR doesn't even know what date_trunc means. AR will just see a string coming out of the database and it will hand it to you without interpretation. You are free to feed that string to ActiveSupport::TimeWithZone (or your favorite time handling class) yourself: there's nothing wrong with telling AR things that it does not and cannot know on its own.
Rails is clever but it isn't magic.