How to get user hour of the week in Ruby - ruby

I want to get the current hour of the week in which day starts from Sunday.
Consider current time is
Time.now
=> 2014-10-29 12:09:23PM +0530
The result should be : 84
Explanation:
Sunday - 24 hours
Monday - 24 hours
Tuesday - 24hours
Wednesday - 12 hours
Total: 84
How can get the user hour of the week. Is there any method available in Ruby ? Or how to do it without Ruby method.

You can get the day of the week and hour of the day using Time#wday and Time#hour.
Time.now.wday
#=> 3
Time.now.hour
#=> 14
The rest is basic mathematics.

Even though I upvoted Yu Hao, I must say it's not a good approach if you want to pay attention to the concerns Jon Skeet raised. To that end, here's another approach:
(Time.now - (Date.today - Date.today.wday).to_time) / 3600
Date.today is, well, today. If you subtract the number of days since the week started, you get Sunday. Convert it to Time and it's the midnight when Sunday began. Subtraction gives you number of seconds between then and now. Divide by 3600 (and optionally round) to get number of hours. The DST details should be transparently handled by Time#-.
EDIT: Timezones... Run this before:
ENV['TZ']='EST5EDT'
(be sure to reset it back to what it used to be afterwards, in case anyone else needs to know time and didn't count on you switching timezones.) You can also use "America/New_York" instead. See tz list for details.

Related

Ruby how to validate date/time to be within at least 24 hours?

I have a date/time format in utc iso8601 like this:
2017-07-12T13:30:44Z
And I'm able to get a "time now" by doing this:
now = Time.now.utc.iso8601
I'm having trouble figuring out how to compare and make sure that the date/time I have in the first block is within the past 24 hours.
There are a handful of ways to handle this. In my opinion the easiest would be to compare the two datetimes.
Something like this:
Rails
datetime >= 1.day.ago && datetime <= Time.now
Vanilla Ruby
This requires you to mess with the date a little more manually, which responds in seconds. So 3600 seconds in an hour, 24 hours in a day.
datetime >= Time.now - (3600 * 24) && datetime <= Time.now
Essentially this is saying "make sure my time object is more recent or equal to 24 hours ago but not a date past right now"

Run a job every other monday

I would like to use Heroku scheduler to run every OTHER Monday. However, it only runs hourly, daily, every 10 minutes.
I read this...
How can I schedule a 'weekly' job on Heroku?
However, I'm not sure what code can be used. I think I can figure out every Monday, but not every OTHER Monday.
thanks
As you get more complicated, I'd recommend checking out scheduling gems. If you want to stick to vanilla Ruby, look at a combination of monday? and cweek, which tells you the week number in the current year. Run your job on Mondays in even-numbered weeks.
date = Date.today
date.monday? && date.cweek.even?
Note that cweek can return 53, since 365 isn't divisible by 7 and it has to handle that last, partial week. The new year's first week will be 1 (it doesn't count from 0), so you have to either skip a week or do two runs in a row when Monday falls in week 53.

Can I specify week 0 in ice_cube gem when I want to a job to run every 2 weeks?

I have this recurring job in our Rails service that sends out emails on Friday every two weeks. However, based on our business requirement, the first week of the "every two weeks" schedule should be this week, which means the email should be sent out this Friday, and then 2 weeks after that, and 4 weeks after that, etc.
The schedule shouldn't be broken when the service restarts. For example, after the email is sent out this Friday, if I restart the service on Saturday, it shouldn't schedule the job to Friday next week -- should still be the Friday of the week after next week. In short, the week 0 should be persistent and stick to this week.
Is it doable in ice_cube? Or are there any other better solution? Thank!
Setting "week 0" is built into IceCube. When you create the schedule, specify the start time rather than Time.now.
2.1.4 :012 > s = IceCube::Schedule.new(Time.now.beginning_of_month)
2.1.4 :013 > s.add_recurrence_rule IceCube::Rule.monthly.count(3)
2.1.4 :014 > s.all_occurrences
=> [2014-12-01 00:00:00 -0500, 2015-01-01 00:00:00 -0500, 2015-02-01 00:00:00 -0500]
Here, I told IceCube the schedule starts at the beginning of this month, although I could have used any value. IceCube computes the schedule based on that time, giving me Dec 1, Jan 1, and Feb 1.

Timegap on heroku servers

I have a strange issue with the scheduler.
I'm sending a reporting that's always referring to the last day, however the reporting always refers to the day before that day. E.g. on the 2nd of January (time of writing this), it's the 31th of december (it has nothing to do with month / year change).
When I log in to the server, the times seem to be correct:
$ date
Do 2. Jan 08:33:48 UTC 2014
# via python:
>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2014, 1, 2, 8, 33, 44, 650541)
# the func that calcs the previous day gives the correct day as well
>>> dates.getBeginningOfYesterday().strftime('%d.%m.%Y')
'01.01.2014'
So, basically I'm not able to reproduce the error, but the scheduler keeps sending with this timegap.
My guess is a local time offset causing you to span a day boundary incorrectly. The examples you show are in UTC, but if you're using a localized timestamp for calculations there could easily be a 5+ hour time offset, causing you to be a day earlier.

CRON: Run job on particular hours

I have a spring batch application and i am using CRON to set how often this application runs. But the problem i am running into is that i want to run the job on specific hours
3 am
7 am
11 am
3 pm
7 pm
11 pm
As you can see it is every 4 hours but starts at 3 am so i cannot use */4 in the hours section of the timing format as this would start the job at 4am
I have also tried '3,7,11,15,19,23' in the hours section but this does not work either (guessing it only works in the minutes section). Does someone know how i can do this?
Use
#Scedule(cron="0 0 3/4 * * ?")
The Pattern x/y means: where <timepart> mod y = x
or
#Scedule(cron="0 0 3,7,11,15,19,21 * * ?")
According to the Quartz Cron Trigger Tutorial:
The '/' character can be used to specify increments to values. For
example, if you put '0/15' in the Minutes field, it means 'every 15th
minute of the hour, starting at minute zero'. If you used '3/20' in
the Minutes field, it would mean 'every 20th minute of the hour,
starting at minute three' - or in other words it is the same as
specifying '3,23,43' in the Minutes field. Note the subtlety that
"/35" does *not mean "every 35 minutes" - it mean "every 35th minute
of the hour, starting at minute zero" - or in other words the same as
specifying '0,35'.
0 0 3,7,11,15,19,23 * * ?
Fires for 0 minute starting at 3am and ending at 23:00 pm every day.
judging by the two answers above the error i was making was i was keeping the apostrophe at the start and end of my hours... very silly
i managed to solve this by using 3-23/4 for the hour as this starts from 3am and then every other fourth hour (just a different way of doing it to the other answers)

Resources