I'm accessing the Evernote API via the evernote gem for ruby on rails, and I'm storing the objects (notebooks, tags, notes, etc.) in a Postgresql database.
Evernote returns timestamps that look like this:
1344141917000
1344141967000
1344138641000
The evernote api documentation says this is the number of milliseconds that have passed since the base time of January 1, 1970, 00:00:00 GMT
I've conducted the following exercise in the rails console in an attempt to reconstruct the date.
evernote_timestamp_base = Time.gm(1970,01,01,00,00,00)
=> 1970-01-01 00:00:00 UTC
evernote_timestamp_base + 1344138641000
=> 44564-01-22 04:43:20 UTC
Definitely not right. But chopping those last three zeros off yields the right date:
evernote_timestamp_base + 1344138641
=> 2012-08-05 03:50:41 UTC
Am I missing something here? What's the deal with those last three zeros? Will I have to parse and chop the evernote timstamp values and then add them to the 1970 base, or is there an easier way?
Also, what's the best Postgresql data type for storing these values?
Thanks in advance for your help.
To do this in Ruby, use Time.at. You'll need to divide by 1000 since Evernote timestamps are in millseconds and Ruby/Unix timestamps are in seconds.
createdNote = noteStore.createNote(authToken, note)
createTime = Time.at(createdNote.created / 1000);
puts "Note was created at #{createTime}"
In postgresql you could use a timestamp [with|without] time zone as the type for the column.
The unix timestamp is defined as the number of seconds since January 1, 1970, 00:00:00 GMT which is what Ruby and many other systems use and or support. PostgreSQL can do the conversion for you to. Just pass the value in seconds to the to_timestamp function.
SELECT to_timestamp(1344138641000/1000.0)
To convert it back use
SELECT EXTRACT(EPOCH FROM col)
Related
I am using ruby 2.2.6 and rails 4.1.16, with pg as database.
I am getting the PG::UndefinedFunction: ERROR : Operator does not exist. timestamp without time zone > time without time zone.
I know this is due to the comparing of different datatype, so I need to change the dataype from the query itself.
I tried looking around and found this guide but it is for rails 5. and another probable solution is to use cast in the sql query.
My query is:
normal = Staff.joins([department: {profils: :schedule_times}], :time_loggers).where(department: selected_departments, status: 1, schedule_times: {day_state: 1, day: wday}, time_loggers: {daterec: date}).where("time_loggers.timein > schedule_times.bstart")
I tried modifying the query by adding a cast to the sql,the query works but didn't return the intended result.
normal = Staff.joins([department: {profils: :schedule_times}], :time_loggers).where(department: selected_departments, status: 1, schedule_times: {day_state: 1, day: wday}, time_loggers: {daterec: date}).where("cast(time_loggers.timein AS TIME) > schedule_times.bstart")
Thanks in advance
EDIT
Actually the query with cast works and returned results, the problem is actually the datacontent.
If I switch the operator to be < as in
where("cast(time_loggers.timein AS TIME) > schedule_times.bstart") then it gives me some results.
time_loggers.timein is Wed, 05 Jan 2022 09:05:00 +08 +08:00
schedule_times.bstart is 2000-01-01 09:00:00 UTC
Now the problem changed already i guess. I need to change the data content directly in the sql before comparing those data, is it possible? Because I need to avoid using each to iterate then compare, as I have thousand of records so the website will be very slow.
What I want is to get those data in my timezone, GMT+8 then only get the hour and minutes and do the comparing.
Or maybe should I post this as another topic?
I managed to work the query.
normal = Staff.joins([department: {profils: :schedule_times}], :time_loggers).where(department: selected_departments, status: 1, schedule_times: {day_state: 1, day: wday}, time_loggers: {daterec: date}).where("to_char(time_loggers.timein + interval '8 hours', 'HH24:MI' > to_char(schedule_times.bstart, 'HH24:MI')")
I converted both timein and bstart using postgres to_char and added 8 hours into timein match the bstart, as it is in GMT+8 using + interval '8 hours.
Special thanks to jad for giving the appropriate direction, that pg documentation is very helpful.
I'm working with a Dataset which gives me a Time Variable for Objects, just like the created_at. The value tho is :
1398037671
Is this a special kind of encoding Timestamps or am i missing something ?
I guess it is "seconds since the Epoch" timestamp
Time.at(1398037671)
2014-04-21 01:47:51 +0200
http://www.ruby-doc.org/core-2.1.1/Time.html#method-c-at
That's a Unix timestamp. That specific timestamp represents 04 / 20 / 14 # 11:47:51pm UTC
You can find out more about them here: http://www.unixtimestamp.com/index.php and at good old wikipedia here: http://en.wikipedia.org/wiki/Unix_time
In Ruby, you can generate a Unix timestamp with Time.now.to_i (or obviously any other time if you don't want the timestamp for now).
I need to get the age of the article in days. For example, the article was written on Tue, 01 Apr 2014 18:31:07 EDT -04:00 and now I need the days from that date to now printed as an integer. How can I do so?
Please try something like this:
gem install time_diff
install the gem.
require 'time_diff'
time_diff_components = Time.diff(start_date_time, end_date_time)
time_diff_components[:year], time_diff_components[:month], time_diff_components[:week]
This will give more option.
More detail click
This isn't the cleverest way, but it's probably the simplest: use a "magic number": 86400, which is the number of seconds in a day. (you probably already know there are 3600 seconds in an hour, mentally file this number alongside that)
Differences between Time/DateTime objects will be in seconds (as a float). If you divide this by 86400 you get the difference in days, as a float. You can then call to_i on this to get it as an integer if you want.
eg
((Time.now - #article.created_at)/86400).to_i
It's probably worth saving this as a constant, egs SECONDS_IN_A_DAY or something, to avoid mistyping.
With the Date class you can do
(Date.today - #article.created_at.to_date).to_i
to get the number of days between the two dates.
I'm writing an app that keeps track of school classes.
I need to store the schedule. For example: Monday-Friday from 8:am-11am.
I was thinking about using a simple string column but I'm going to need to make time calculations later.
For example, I need to store a representation of 8am, such as start_at:8am end_at:11am
So how should I store the time? What datatype should I use? Should I store start time and number of seconds or minutes and then calculate from there? or is there an easier way?
I use MySQL for production and SQLite for development.
I made an app recently that had to tackle this problem. I decided to store open_at and closed_at in seconds from midnight in a simple business hour model. ActiveSupport includes this handy helper for finding out the time in seconds since midnight:
Time.now.seconds_since_midnight
This way I can do a simple query to find out if a venue is open:
BusinessHour.where("open_at > ? and close_at < ?", Time.now.seconds_since_midnight, Time.now.seconds_since_midnight)
Any tips for making this better would be appreciated =)
If you're using Postgresql you can use a time column type which is just the time of day and no date. You can then query
Event.where("start_time > '10:00:00' and end_time < '12:00:00'")
Maybe MySQL has something similar
Check out the gem 'tod' for Rails 4 or Time_of_Day for Rails 3. They both solve the problem of storing time in a database while using an an Active Record model.
SQL has a time data type but Ruby does not. Active Record addresses this difference by representing time attributes using Ruby’s Time class on the canonical date 2000-01-01. All Time attributes are arbitrarily assigned the same dates. While the attributes can be compared with one another without an issue, (the dates are the same), errors arise when you attempt to compare them with other Time instances. Simply using Time.parse on a string like ”10:05” adds today’s date to the output.
Lailson Bandeira created a created solution for this problem, the Time_of_Day gem for Rails 3. Unfortunately the gem is no longer maintained. Use Jack Christensen’s ‘tod’ gem instead. It works like a charm.
This ruby gem converts time of day to seconds since midnight and back. The seconds value is stored in the database and can be used for calculations and validations.
Define the time of day attributes:
class BusinessHour < ActiveRecord::Base
time_of_day_attr :opening, :closing
end
Converts time of day to seconds since midnight when a string was set:
business_hour = BusinessHour.new(opening: '9:00', closing: '17:00')
business_hour.opening
=> 32400
business_hour.closing
=> 61200
To convert back to time of day:
TimeOfDayAttr.l(business_hour.opening)
=> '9:00'
TimeOfDayAttr.l(business_hour.closing)
=> '17:00'
You could also omit minutes at full hour:
TimeOfDayAttr.l(business_hour.opening, omit_minutes_at_full_hour: true)
=> '9'
I would store the starting hour and the duration within the database, using two integer columns.
By retrieving both values, you could convert the starting hour as in (assuming that you know the day already:
# assuming date is the date of the day, datetime will hold the start time
datetime = date.change({:hour => your_stored_hour_value , :min => 0 , :sec => 0 })
# calculating the end time
end_time = datetime + your_stored_duration.seconds
Otherwise, hava a look at Chronic. The gem makes handling time a little bit easier. Note that the changemethod is part of rails, and not available in plain Ruby.
The documentation on DateTime for plain Ruby can be found here.
Also, whatever you do, don't start storing your dates/time in 12-hour format, you can use I18nin Rails to convert the time:
I18n.l Time.now, :format => "%I.%m %p", :locale => :"en"
I18n.l Time.now + 12.hours, :format => "%I.%m %p", :locale => :"en"
You can also get from this notation, that you can store you duration in hours, if you want, you can then convert them rather easily by:
your_stored_value.hours
if stored as an integer, that is.
Suggestion:
Don’t worry about a specific datatype for that. A simple solution would be:
In the database, add an integer type column for start_time and another for end_time. Each will store the number of minutes since midnight.
Ex: 8:30am would be stored as 510 (8*60+30)
In the form, create a select field (dropdown) that displays all available times in time format:Ex.: 10am, 10:30am and so on.
But the actual field values that get saved in the database are their integer equivalents:
Ex: 600, 630 and so on (following the example above)
I assume you are using some kind of database for this. If you are using MySQL or Postgresql, you can use the datetime column type, which Ruby/Rails will automatically convert to/from a Time object when reading/writing to the database. I'm not sure if sqlite has something similar, but I imagine it probably does.
From the SQLite 3 website,
"SQLite does not have a storage class set aside for storing dates and/or times. Instead, the built-in Date And Time Functions of SQLite are capable of storing dates and times as TEXT, REAL, or INTEGER values:
TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS").
REAL as Julian day numbers, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic Gregorian calendar.
INTEGER as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.
Applications can chose to store dates and times in any of these formats and freely convert between formats using the built-in date and time functions."
You can then manipulate the values using the Date and Time functions outlined here.
How can I convert a php timestamp to something that is usable in actionScript? For example, how could I use the following timestamp?
2011-06-16 10:41:08
The timestamp is currently stored in xml.
#Marc B's answer is correct. If for some reason you can't use the PHP timestamp (number of seconds since Jan 1, 1970), you can try the static method Data.parse().
It will return the number of miliseconds since Jan 1, 1970 based on your time string. It will process various time string formats, here's a link to the docs. You might have to tweak your time string into one of these formats (using a regular expression on the Actionscript side, or by generating a different string on the PHP side).
Once you get the number of milliseconds since Jan 1, 1970, you can then create a new Actionscript Date object from that:
var date:Date = new Date( Date.parse(myTimeString) );
That's not a PHP timestamp, it's just a formatted string. PHP timestamps are the same as unix timestamps - an integer representing seconds since Jan 1/1970.
Actionscripts timestamps are the same, but in milliseconds. So take a native PHP timestamp, multiply by 1000, and there's your AS timestamp.