Find days of week based on weekdays mask value - ruby-on-rails

I have a weekdays mask number which represents the sum of some days of the week:
SUNDAY = ((2**0))
MONDAY = ((2**1))
TUESDAY = ((2**2))
weekdays_mask = SUNDAY + MONDAY + TUESDAY
So if I have the sum of these days stored in DB how can I do the reverse process and find what days of week I will have to display based on the weekdays_mask value. Does anyone know a method for doing this? Thank you!

+ is a bit uncommon. You'd usually use bitwise OR to combine the values:
SUNDAY | MONDAY | TUESDAY #=> 7
SUNDAY | MONDAY #=> 3
and bitwise AND to check for a specific value:
days = SUNDAY | MONDAY
days & SUNDAY #=> 1
days & MONDAY #=> 2
days & TUESDAY #=> 0 <- zero indicates bit not set

You could initialise them by the 0b0000-like pattern and instead of +/- then use binary arithmetics instead;
SUNDAY = 0b000000
MONDAY = 0b000001
TUESDAY = 0b000010
WEDNESDAY = 0b000100
THURSDAY = 0b001000
FRIDAY = 0b010000
SATURDAY = 0b100000
weekend = SATURDAY | SUNDAY
workday = MONDAY | TUESDAY | WEDNESDAY | THURSDAY | FRIDAY
is_friday_weekend = weekend & FRIDAY
# => 0
is_friday_workday = workday & FRIDAY
# => 16 (Which is not 0; so yes)

I'm sure there is a cleaner way, bit here my 2 cents, based on three days, but works also adding more days:
SUNDAY = ((2**0))
MONDAY = ((2**1))
TUESDAY = ((2**2))
weekdays_mask_7 = SUNDAY | MONDAY | TUESDAY
weekdays_mask_6 = MONDAY | TUESDAY
weekdays_mask_5 = SUNDAY | TUESDAY
weekdays_mask_4 = TUESDAY
weekdays_mask_3 = SUNDAY | MONDAY
weekdays_mask_2 = MONDAY
weekdays_mask_1 = SUNDAY
days = %w[SUNDAY MONDAY TUESDAY]
weekdays_mask = weekdays_mask_7 # just to play
day_array = (weekdays_mask.to_s(2).split("").map(&:to_i).reverse).zip(days)
day_array.select{|e| p e[1] if e[0] == 1}

Related

NSDateComponents: Get nearest future date

I am creating date components and using the largest unit to display
For example:
1 day 23 hour 2 minute -> 2 days to go (as hour is close to next day
+1 day value)
1 day 10 hour 53 minute -> 1 day to go
0 day 10 hour 50 minute -> 11 hours to go (as minutes are close to next hour +1 hour value)
I'm using below logic to create components
NSCalendar *const calendar = [NSCalendar currentCalendar];
NSDateComponents *const components = [calendar components:(NSCalendarUnitDay |
NSCalendarUnitHour |
NSCalendarUnitMinute)
fromDate:[NSDate date]
toDate:date
options:NSCalendarWrapComponents];
if components.day {return components.day}
if components.hour {return components.hour}
if component.minute {return component.minute}
But above code returns below
1 day 23 hour 2 minute -> 1 day to go
1 day 10 hour 53 minute -> 1 day to go
0 day 10 hour 50 minute -> 10 hours to go
Is there any formatter options that can be used to get rounded up day/hour based upon value of hour/minutes after that?
I know I can check for value of hour if day is present and +1 the day but i'm looking if theres anything supported from iOS

How to sort a table in Lua based on current date

I need an array which will start with today's date as the first element and sort all of the others in that order.
self.dayw=tonumber(os.date("%w")) --today's date
this is the array I have already implemented
self.dayArray[1]=response["monday"]
self.dayArray[2]=response["tuesday"]
self.dayArray[3]=response["wednesday"]
self.dayArray[4]=response["thursday"]
self.dayArray[5]=response["friday"]
self.dayArray[6]=response["saturday"]
self.dayArray[7]=response["sunday"]
So if today is Friday, I need that array to start from Friday as the first element.
I have created sortArray={} and tried to fill it with elements depending on the day, but the code is too "hectic" and there is probably a smarter solution to this. If you can please help.
Each day of the week is assigned a number, starting from Sunday at 1 and ending with Saturday at 7. In order to find this numerical representation of the current day, call os.date("*t"), which returns a table filled with information about the current day, month, year, etc. The field within this table that corresponds to the current day's number is called wday.
for k, v in pairs(os.date("*t")) do
print(k, v)
end
Output:
year 2020
wday 6
month 8
isdst true
hour 21
day 28
sec 13
yday 241
min 48
Here, the value associated with key wday is 6, which corresponds to Friday.
With this number, you can reorder your table of days by popping elements before the current day and then reinserting them at the end.
-- Local references to table functions.
local tblins = table.insert
local tblrmv = table.remove
local days = {
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
}
local function reorder(days, wday)
for i = wday - 1, 1, -1 do
-- Pop element days[1] and then append it.
tblins(days, tblrmv(days, 1))
end
return
end
local date_table = os.date("*t")
reorder(days, date_table.wday)
for i, day in ipairs(days) do
print(i, day)
end
Output:
1 Friday
2 Saturday
3 Sunday
4 Monday
5 Tuesday
6 Wednesday
7 Thursday
If you wanted an easily restartable version, here is an expansion of my existing solution:
-- Local references to table functions.
local tblins = table.insert
local tblrmv = table.remove
local tblsrt = table.sort
-- The field `day' refers to the string representation; `num' refers to the
-- given day's original position in the table, which is used to restore the
-- table to its starting order.
local days = {
{day = "Sunday", num = 1},
{day = "Monday", num = 2},
{day = "Tuesday", num = 3},
{day = "Wednesday", num = 4},
{day = "Thursday", num = 5},
{day = "Friday", num = 6},
{day = "Sunday", num = 7}
}
local function sort_days(left_day, right_day)
return left_day.num < right_day.num
end
-- The reorder function remains the same
-- To put the days table back in its original order, call the following:
tblsrt(days, sort_days)
for i, day in ipairs(days) do
print(i, day.day, day.num)
end
Output:
1 Sunday 1
2 Monday 2
3 Tuesday 3
4 Wednesday 4
5 Thursday 5
6 Friday 6
7 Saturday 7

Ruby on rails get hours, minutes, seconds from two dates and times

I need the number of hours, minutes, seconds between two dates and times.I'm able to get the number of days, hours, minutes, seconds but I don't want no.of days instead of it, I need hours, minutes, seconds only enough.
Here my code,
start_time is Wed, 13 Dec 2017 20:35:19 -0800 and end_time is today datetime
def time_diff(end_time, start_time)
diff = end_time - start_time
mm, ss = diff.divmod(60)
hh, mm = mm.divmod(60)
dd, hh = hh.divmod(24)
time = "%d h, %d m, %d s" % [hh, mm, ss]
return time
end
I need output like this "35 h, 29 m, 12 s"
Thanks for your help.
Just out of curiosity, a pure [almost] functional solution, without intermediate local variables:
start_time = DateTime.parse 'Wed, 13 Dec 2017 23:00:00 UTC'
end_time = DateTime.parse 'Wed, 15 Dec 2017 23:30:20 UTC'
sec, min, hrs = [60, 60, 1].
map.
with_object([[[end_time, start_time].
map(&:to_time).
map(&:to_i).
reduce(:-), nil]]) do |div, obj|
obj << obj.last.first.divmod(div)
obj[-2].rotate!
end.
map(&:first).
compact
#⇒ [20, 30, 48]
You've already got the answer - just don't divide by 24!
If the start_time and end_time are DateTime value you can use the following
difference = end_time - start_time
hours = (difference * 24).to_i
minutes = (difference * 24 * 60).to_i
seconds = (difference * 24 * 60 * 60).to_i

Ruby on Rails - Get date - given is year, month, weeknumber and day

I have some troubles with the following task:
Given are the following parameters:
Year: 2016
Month: 2
Week of Month: 2
Day of week: Monday
The result should be 2016-02-08
Is there a method to get this?
Thanks in advance
A way to do this would be
weekday_index = {monday: 1, tuesday: 2, wednesday: 3, thursday: 4, friday: 5, saturday: 6, sunday: 7}
day_in_a_week = 7
year = year_param # 2016
month = month_param # 8
week_number = 2
day_of_month = (week_number * days_in_a_week) - (days_in_a_week - weekday_index[:monday])
Date.new(year, month, day_of_month).to_s
You can use this code. Values used were supplied in the question month = 2, week_number = 2 and year = 2016
month = 2
year = 2016
week_number = 2
FIRST_DAY = 1 #first day of every month
day = { monday: 1, tuesday: 2, wednesday: 3, thursday: 4, friday: 5, saturday: 6, sunday: 7}
first_wk_of_month = Date.new(year, month, FIRST_DAY).cweek #=> 05
date_week_num = first_wk_of_month + (week_number - 1) #=> 06
date = Date.commercial(year, date_week_num, day[:monday]).to_s # 2016-02-08
There are 52 weeks in a year and a month can have as low as 1 day in a week if it starts on Sunday. Taking that into consideration,
first_wk_of_month finds the week number in the year (between 1 and 52) on which the month in question starts.
date_week_num finds the actual week number in the year the date falls on. In this scenario which is 2nd week of February it returns 6 representing the 6th week of the year
Passing the date_week_num and the day to the Date.commercial allows us to find the date
Tested it with a couple of days and works fine. You could probably change the variable names. Hope this solves your challenge

NSDateComponents returns wrong weekday

If you'll run this code:
// January 16th 2015 10:20 AM in Amsterdam
var date = NSDate(timeIntervalSince1970: 1421400000)
var formatter = NSDateFormatter()
formatter.dateFormat = "dd-MMM"
let calendar = NSCalendar.currentCalendar()
calendar.firstWeekday = 2 // default when region == Netherlands
let units = NSCalendarUnit.YearCalendarUnit | NSCalendarUnit.MonthCalendarUnit
| NSCalendarUnit.WeekOfMonthCalendarUnit | NSCalendarUnit.DayCalendarUnit
| NSCalendarUnit.WeekdayCalendarUnit
// Loop days in January
for day in 1...14 {
// select day in month
var components = calendar.components(units, fromDate: date)
components.day = day
// get day and components
let _date = calendar.dateFromComponents(components)!
var _components = calendar.components(units, fromDate: _date)
// retrieve characteristics
let weekOfMonth = _components.weekOfMonth
let dayOfWeek = _components.weekday
let month = _components.month
println("\(formatter.stringFromDate(_date)) is day \(dayOfWeek) of week \(weekOfMonth) of month \(month) \n")
}
You'll probably get back:
01-Jan is day 5 of week 1 of month 1
02-Jan is day 6 of week 1 of month 1
03-Jan is day 7 of week 1 of month 1
04-Jan is day 1 of week 1 of month 1
05-Jan is day 2 of week 2 of month 1
06-Jan is day 3 of week 2 of month 1
07-Jan is day 4 of week 2 of month 1
....
Those weekdays are wrong.
Not only should the the 1st of january be the 4th day (a thursday), it's also strange that the 3rd of january seems to be on day 7 of week 1 and the 4th of january seems to be day 1 of that same week.
Obviously I'm doing something wrong here, who could help me out?
When you remove the calendar.firstWeekday = 2 line you'll get:
01-Jan is day 5 of week 1 of month 1
02-Jan is day 6 of week 1 of month 1
03-Jan is day 7 of week 1 of month 1
04-Jan is day 1 of week 2 of month 1
05-Jan is day 2 of week 2 of month 1
06-Jan is day 3 of week 2 of month 1
07-Jan is day 4 of week 2 of month 1
....
That makes more sense, but I really need the first day of the week to be a monday here..
I've set up a demo project for you to test this behaviour yourself. https://github.com/tiemevanveen/NSDateComponentsTest/tree/master
As sha points out, components.weekday does not change if your week does not start on a sSnday. Strange that components.weekOfMonth does change when your week starts on Monday..
Solution to my problem
An answer to another question let me to a way to find the desired weekday if the calendar's week does not start with a Sunday.
dayOfWeek = calendar.ordinalityOfUnit(.WeekdayCalendarUnit, inUnit: .WeekCalendarUnit, forDate: _date)
That code could also be used to find the week of the month or the month itself:
dayOfWeek = calendar.ordinalityOfUnit(.WeekdayCalendarUnit, inUnit: .WeekCalendarUnit, forDate: _date)
month = calendar.ordinalityOfUnit(.MonthCalendarUnit, inUnit: .YearCalendarUnit, forDate: _date)
It's all correct. If you look at Apple Documentation.
you can see that 1 is Sunday, 2 - is Monday and so forth. So 5 is Thursday as expected.

Resources