ROR + Ruby Date Decrease by 15 minutes - ruby

If I have #time = Time.now.strftime("%Y-%m-%d %H:%M:%S"),
How can I reduce this time by 15 minutes ?
I already tried this one :: #reducetime = #time-15.minutes, works fine at console but give errors while execution. Other than this Is there any way to resolve this issue.
Thanks

Your problem is that you're formatting your time into a string before you're done treating it as a time. This would make more sense:
#time = Time.now
#reducetime = #time - 15.minutes
# And then later when you're reading to display #time...
formatted_time = #time.strftime("%Y-%m-%d %H:%M:%S")
You shouldn't format your data until right before you're ready to display it.
If you must have #time as the formatted time then you're going to have to parse it before computing #reducetime:
#reducetime = (DateTime.strptime(#time, "%Y-%m-%d %H:%M:%S") - 15.minutes).to_time

Related

(Micropython) Creating and comparing time objects

Using Micropython for the ESP32 microcontroller, flashed with the latest firmware at time of writing (v1.18)
I'm making an alarm (sort-of) system where I get multiple time values ("13:15" for example) from my website, and then I have to ring an alarm bell at those times.
I've done the website and I can do the ring stuff, but I don't know how to actually create time objects from the previously mentioned strings ("13:15"), and then check if any of the times inputted match the current time, the date is irrelevant.
From reading the documentation, im getting the sense that this cant be done, since ive looked through the micropython module github, and you apparently cant get datetime in micropython, and i know that in regular python my problem can be solved with datetime.
import ntptime
import time
import network
# Set esp as a wifi station
station = network.WLAN(network.STA_IF)
# Activate wifi station
station.active(True)
# Connect to wifi ap
station.connect(ssid,passwd)
while station.isconnected() == False:
print('.')
time.sleep(1)
print(station.ifconfig())
try:
print("Local time before synchronization: %s" %str(time.localtime()))
ntptime.settime()
print("Local time after synchronization: %s" %str(time.localtime()))
except:
print("Error syncing time, exiting...")
this is the shortened code from my project, with only the time parts, now comes into play the time comparison thing I don't know how to do.
Using ntptime to get time from server. I use "time.google.com", to get the time. Then, I transform it into seconds (st) to be more accurate. And set my targets hour in seconds 1 hour = 3600 s.
import utime
import ntptime
def server_time():
try:
# Ask to time.google.com server the current time.
ntptime.host = "time.google.com"
ntptime.settime()
t = time.localtime()
# print(t)
# transform tuple time 't' to seconds value. 1 hour =
st = t[3]*3600 + t[4]*60 + t[5]
return st
except:
# print('no time')
st = -1
return st
while True:
# Returns an increasing millisecond counter since the Board reset.
now = utime.ticks_ms()
# Check current time every 5000 ms (5s) without going to sleep or stop any other process.
if now >= period + 5000:
period += 5000
# call your servertime function
st = server_time()
if ((st > 0) and (st < 39600)) or (st > 82800): # Turn On 17:00 Mexico Time.
# something will be On between 17:00 - 06:00
elif ((st <82800) and (st > 39600)): # Turn Off 6:00.
# something will be Off between 06:00 - 17:00
else:
pass
After running ntptime.settime() you can do the following to retrieve the time, keep in mind this is in UTC:
rtc = machine.RTC()
hour = rtc.datetime()[4] if (rtc.datetime()[4]) > 9 else "0%s" % rtc.datetime()[4]
minute = rtc.datetime()[5] if rtc.datetime()[5] > 9 else "0%s" % rtc.datetime()[5]
The if else statement makes sure that numbers lower or equal to 9 are padded with a zero.

Ruby Date Time Subtraction

I am trying to calculate the exact duration a process took from some log file result. After parsing the log, I reached at the following stage:
my_array = ["Some_xyz_process", "Start", "2018-07-12", "12:59:53,397", "End", "2018-07-12", "12:59:55,913"]
How can I subtract the start date and time from the end date and time in order to retrieve the exact duration the process took?
my_array = ["Some_xyz_process",
"Start", "2018-07-12", "12:59:53,397",
"End", "2018-07-12", "12:59:55,913"]
require 'date'
fmt = '%Y-%m-%d%H:%M:%S,%L'
is = my_array.index('Start')
#=> 1
ie = my_array.index('End')
#=> 4
DateTime.strptime(my_array[ie+1] + my_array[ie+2], fmt).to_time -
DateTime.strptime(my_array[is+1] + my_array[is+2], fmt).to_time
#=> 2.516 (seconds)
See DateTime#strptime and DateTime# (the latter for format directives). As long as the date and time formats are known I always prefer strptime to parse. Here's an example of why:
DateTime.parse 'Theresa May has had a bad week over Brexit'
#=> #<DateTime: 2018-05-01T00:00:00+00:00 ((2458240j,0s,0n),+0s,2299161j)>`.
You can concat the date and time field and use Time.parse to convert it to a time object and then calculate the difference in number of seconds
Time.parse('2018-07-12 12:59:55,397').to_i - Time.parse('2018-07-12 12:59:53,913').to_i
Hope this helps

compare times with milliseconds

I have two dates a start date and an end date. I want to get a new time object which is the difference between the two. The differences I am concerned with are Hours, Minutes, Seconds and Milliseconds. I need to be able to create a new Time object from the result that includes the milliseconds difference
>> require 'time'
=> true
>> start_time = Time.parse '1970-01-01T00:00:00.200'
=> 1970-01-01 00:00:00 +0000
>> end_time = Time.parse '1970-01-01T01:01:01.400'
=> 1970-01-01 01:01:01 +0000
>> difference = Time.at(end_time - start_time)
=> 1970-01-01 01:01:01 +0000
my problem is that difference does not have the milliseconds
I can see that the Time has milliseconds by running
>> difference.strftime('%H:%M:%S.%L')
=> "01:01:01.199"
but how do I access the milliseconds that are in the Time difference object.
it is critical I have milliseconds as I am working in sub-second calculations?
UPDATE
I don't think my first attempt at this question was as descriptive as it should of been, my apologies for that.
require 'time'
a = Time.now
sleep(0.5)
b = Time.now
b - a
# => 0.505087
Milliseconds!
EDIT: Microseconds!
my problem is that difference does not have the milliseconds
It does have the milliseconds, Time#to_s / Time#inspect just doesn't show it. Its output is equivalent to: strftime "%Y-%m-%d %H:%M:%S %z"
how do I access the milliseconds that are in the Time difference object.
usec returns the microseconds and nsec returns the nanoseconds:
time = Time.at(0.2)
time.usec #=> 200000
time.nsec #=> 200000000
For milliseconds you could use
time.usec / 1000 #=> 200
Ruby's Time class has nanosecond precision: you can use Time#to_f to get a fractional number of seconds since the Unix epoch. If you subtract two Time objects, you'll get a fractional number of seconds between them. Thus, to get the number of milliseconds between two times, try:
((time2 - time1) * 1000).to_i

Ruby time subtraction

There is the following task: I need to get minutes between one time and another one: for example, between "8:15" and "7:45". I have the following code:
(Time.parse("8:15") - Time.parse("7:45")).minute
But I get result as "108000.0 seconds".
How can I fix it?
The result you get back is a float of the number of seconds not a Time object. So to get the number of minutes and seconds between the two times:
require 'time'
t1 = Time.parse("8:15")
t2 = Time.parse("7:45")
total_seconds = (t1 - t2) # => 1800.0
minutes = (total_seconds / 60).floor # => 30
seconds = total_seconds.to_i % 60 # => 0
puts "difference is #{minutes} minute(s) and #{seconds} second(s)"
Using floor and modulus (%) allows you to split up the minutes and seconds so it's more human readable, rather than having '6.57 minutes'
You can avoid weird time parsing gotchas (Daylight Saving, running the code around midnight) by simply doing some math on the hours and minutes instead of parsing them into Time objects. Something along these lines (I'd verify the math with tests):
one = "8:15"
two = "7:45"
h1, m1 = one.split(":").map(&:to_i)
h2, m2 = two.split(":").map(&:to_i)
puts (h1 - h2) * 60 + m1 - m2
If you do want to take Daylight Saving into account (e.g. you sometimes want an extra hour added or subtracted depending on today's date) then you will need to involve Time, of course.
Time subtraction returns the value in seconds. So divide by 60 to get the answer in minutes:
=> (Time.parse("8:15") - Time.parse("7:45")) / 60
#> 30.0

Rolling list over unequal times in XTS

I have stock data at the tick level and would like to create a rolling list of all ticks for the previous 10 seconds. The code below works, but takes a very long time for large amounts of data. I'd like to vectorize this process or otherwise make it faster, but I'm not coming up with anything. Any suggestions or nudges in the right direction would be appreciated.
library(quantmod)
set.seed(150)
# Create five minutes of xts example data at .1 second intervals
mins <- 5
ticks <- mins * 60 * 10 + 1
times <- xts(runif(seq_len(ticks),1,100), order.by=seq(as.POSIXct("1973-03-17 09:00:00"),
as.POSIXct("1973-03-17 09:05:00"), length = ticks))
# Randomly remove some ticks to create unequal intervals
times <- times[runif(seq_along(times))>.3]
# Number of seconds to look back
lookback <- 10
dist.list <- list(rep(NA, nrow(times)))
system.time(
for (i in 1:length(times)) {
dist.list[[i]] <- times[paste(strptime(index(times[i])-(lookback-1), format = "%Y-%m-%d %H:%M:%S"), "/",
strptime(index(times[i])-1, format = "%Y-%m-%d %H:%M:%S"), sep = "")]
}
)
> user system elapsed
6.12 0.00 5.85
You should check out the window function, it will make your subselection of dates a lot easier. The following code uses lapply to do the work of the for loop.
# Your code
system.time(
for (i in 1:length(times)) {
dist.list[[i]] <- times[paste(strptime(index(times[i])-(lookback-1), format = "%Y-%m-%d %H:%M:%S"), "/",
strptime(index(times[i])-1, format = "%Y-%m-%d %H:%M:%S"), sep = "")]
}
)
# user system elapsed
# 10.09 0.00 10.11
# My code
system.time(dist.list<-lapply(index(times),
function(x) window(times,start=x-lookback-1,end=x))
)
# user system elapsed
# 3.02 0.00 3.03
So, about a third faster.
But, if you really want to speed things up, and you are willing to forgo millisecond accuracy (which I think your original method implicitly does), you could just run the loop on unique date-hour-second combinations, because they will all return the same time window. This should speed things up roughly twenty or thirty times:
dat.time=unique(as.POSIXct(as.character(index(times)))) # Cheesy method to drop the ms.
system.time(dist.list.2<-lapply(dat.time,function(x) window(times,start=x-lookback-1,end=x)))
# user system elapsed
# 0.37 0.00 0.39

Resources