I'm using rails 3 and I want to change the default date format of created_at and updated_at date when I save them into the db.
Default date format is %Y-%m-%d %H:%M:%S, but
I would like it to be %Y%m%d%H%M%S
Where should I change the format? I'm trying to create a time_formats.rb in the initializer folder.
Here is content:
class TimeFormats
Time::DATE_FORMATS[:db] = "%Y%m%d%H%M%S"
Time::DATE_FORMATS[:default] = "%Y%m%d%H%M%S"
end
This does not work. Is there someone who can help me? Thank you.
The time and date formats that you define in the initializers apply only when converting them to strings in Ruby. The formats you've defined would be used like Time.now.to_s(:default).
I don't recommend (nor am I aware of a way how) to change how dates are stored in the database. You should let the database store them as it does by default, then change how they are formatted in the views using .to_s(:format) as defined in the initializers.
Normally the database stores the timestamps as a specific timedate datatype rather than a formatted string. If you just want default timestamp printing style to be different, you might try overriding the created_at and updated_at methods:
def updated_at
super.strftime("%Y%m%d%H%M%S")
end
Related
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 am converting string into date in my rails application model before saving it into database, how to achieve this using without
strptime
because strptime purpose is to format and used for views and helpers .
string format:
"04-28-2015"(mm-dd-yy)
model:
def rent_commencement_date=(value)
self[:rent_commencement_date] = Date.strptime(value, "%m-%d-%Y").to_s(:db)
end
You can use to_date to convert string into date.
Eg: "01-01-2015".to_date
use it. i think this is helpful for you
date = DateTime.now
puts date.to_date.to_s
Or
"2011-05-19 10:30:14".to_time
Used american_date gem, it automatically coverts american date format into ISO format. no need to use setter to format the date in model.
gem 'american_date'
I would like to present a datetime select to the user in their preferred time zone but store the datetime as UTC. Currently, the default behavior is to display and store the datetime field using UTC. How can I change the behavior of this field without affecting the entire application (i.e. not changing the application default time zone)?
Update: This is not a per-user timezone. I don't need to adjust how times are displayed. Only these specific fields deal with a different time zone, so I would like the user to be able to specify the time in this time zone.
Here's how you can allow the user to set a date using a specific time zone:
To convert the multi-parameter attributes that are submitted in the form to a specific time zone, add a method in your controller to manually convert the params into a datetime object. I chose to add this to the controller because I did not want to affect the model behavior. You should still be able to set a date on the model and assume your date was set correctly.
def create
convert_datetimes_to_pdt("start_date")
convert_datetimes_to_pdt("end_date")
#model = MyModel.new(params[:my_model])
# ...
end
def update
convert_datetimes_to_pdt("start_date")
convert_datetimes_to_pdt("end_date")
# ...
end
def convert_datetimes_to_pdt(field)
datetime = (1..5).collect {|num| params['my_model'].delete "#{field}(#{num}i)" }
if datetime[0] and datetime[1] and datetime[2] # only if a date has been set
params['my_model'][field] = Time.find_zone!("Pacific Time (US & Canada)").local(*datetime.map(&:to_i))
end
end
Now the datetime will be adjusted to the correct time zone. However, when the user goes to edit the time, the form fields will still display the time in UTC. To fix this, we can wrap the fields in a call to Time.use_zone:
Time.use_zone("Pacific Time (US & Canada)") do
f.datetime_select :start_date
end
There are a couple of options:
Utilize the user's local timezone when displaying data to them. This is really easy with something like the browser-timezone-rails gem. See https://github.com/kbaum/browser-timezone-rails. It is essentially overriding the application timezone for each request based on the timezone detected from the browser. NOTE: it only uses the OS timezone, so it's not as accurate as an IP/geo based solution.
Setup your application timezone so that it is consistent with the majority of your user base. For example: config.time_zone = 'Mountain Time (US & Canada)'. This is a very standard thing to do in rails. Rails will always store the data in the DB as UTC, but will present / load it using the application timezone.
Create a timezone for your user model. Allow users to set this value in their account settings. And, then use a similar approach to that of the above gem does in the application_controller.
I have Rails3 application with model user and field expires_at created like this:
t.column :expires_at, :timestamp
In my database (postgresql) it has type:
timestamp without timezone
The problem is when I call:
#user.expires_at = Time.now
#user.save
it is saved into database with UTC timezone (my local time is UTC + 1:00, Warsaw) but I don't want that. I just want to have time with my local timezone saved into the database (2011-03-30 01:29:01.766709, not 2011-03-29 23:29:01.766709)
Can I achieve this using rails3?
For saving time in local timezone to database this has to be set in application.rb
config.active_record.default_timezone = :local
If you only want to use local times on certain columns, rather than as a global setting, then the Rails documentation tells us this:
# If your attributes are time zone aware and you desire to skip time zone conversion to the current Time#zone when reading certain attributes then you can do following:
class Topic < ActiveRecord::Base
self.skip_time_zone_conversion_for_attributes = [:written_on]
end
(This also skips time zone conversion on writing, not just reading). And you can pass in an array of symbols for multiple attributes.
I am not sure which versions of Rails this was introduced in, though.
I've run into a spot of bother with date formats in our Rails application.
I have a date field in our view which I want to be formatted as dd/mm/yy. This is how the user will expect to enter their dates, and the datepicker control uses this format.
However, Active Record seems to be expecting mm/dd/yy.
If I enter 01/03/2010, this gets put in as 03 January 2010.
If I enter 25/03/2010, this gets put in a null.
How do I get ActiveRecord to expect Her Majesties date format?
Rails' DateTime tries to detect the formatting automatically. It will detect the following formats: mm/dd/yy or dd-mm-yy or yyyy-mm-dd or yyyy/mm/dd. You could monkey-patch DateTime.parse, but I would rather move this issue to the View of your application.
I always recommend to use yyyy-mm-dd [hh:mm:ss] as a string representation for a date. Check the documentation of your DatePicker if it supports multiple date-formats.
The jQuery date-picker for example has this covered with dateFormat (for the data that is sent to the server, set this to yyyy-mm-dd) as well as altFormat (for the input the user sees, set this to dd/mm/yyyy).
Add a file called rails_defaults.rb to config\initializers directory; with following lines:
Date::DATE_FORMATS[:default] = '%d/%m/%Y'
Time::DATE_FORMATS[:default]= '%d/%m/%Y %H:%M:%S'
Restart the server and you are good to go.
class Date
class << self
def _parse_with_us_format(date, *args)
if date =~ %r{^(\d+)/(\d+)/(\d+)$}
_parse_without_us_format("#{$3.length == 2 ? "20#{$3}" : $3}-#{$1}-#{$2}", *args)
else
_parse_without_us_format(date, *args)
end
end
alias_method_chain :_parse, :us_format
end
end