Determining which Sunday in Ruby - ruby

Using Ruby how can you determine if the coming Sunday is the first, second or third Sunday of the month?

#ElYusubov - is close, but not quite right.
As a starting point, the division must be by seven (number of days in a week). But time.day gives a day-of-the-month from 1 to 31, so first you need to subtract one before the division and add one after. The first eight days of any month give...
Day number (Day# - 1) / 7 Week#
---------- -------------- -----
1 0.0 1
2 0.14 1
3 0.29 1
4 0.43 1
5 0.57 1
6 0.71 1
7 0.86 1
8 1 2
Whichever day-of-the-week time.day gives, that week# indicates whether it's the first, second etc of that day-of-the-week. But you want the coming Sunday.
wday gives a weekday - 0 to 6, with 0 meaning Sunday. So how many days are there to the coming Sunday? Well, that depends on your definition of "Coming", but if you exclude today==Sunday, you basically subtract todays weekday from 7.
Weekday today Days until next Sunday
------------- ----------------------
0 (Sun) 7
1 (Mon) 6
2 (Tue) 5
3 (Wed) 4
4 (Thu) 3
5 (Fri) 2
6 (Sat) 1
If you allow the "coming" Sunday to be today, then you do the same thing but replace seven with zero. You can either do a conditional check, or use the modulo/remainder operator.
Anyway, once you know how many days ahead the coming Sunday is, you can calculate the date value for that (add those days to todays date) and then determine the week number in the month for that date instead of today using the first method (subtract 1, divide by seven, add 1).
Relevant vocabulary...
Date.wday 0 to 6 (0 = sunday)
Date.day 1 to 31
I won't try to provide the code because I don't know Ruby.

Related

Avg of avgs in variable time windows

Context:
Activity has a grade
Activities belong to a subject, and the subject_avg is simply the average of its activities grades in a determined time range
The global_avg is the avg of many subject_avg (i.e, not to be confused with the average of all activity grades)
Problem:
"Efficiently" calculate global_avg in variable time windows
"Efficiently" calculating subject_avg for a single subject, by accumulating the amount and grade of its activities:
date
grade
act1
day 1
0.5
act2
day 3
1
act3
day 3
0.8
act4
day 6
0.6
act5
day 6
0
avg_sum
activity_count
day 1
0.5
1
day 3
2.3
3
day 6
2.6
5
I called it "efficiently" because if I need subject_avg between any 2 dates, I can obtain it with simple arithmetic over the second table:
subject_avg (day 2 to 5) = (2.3 - 0.5) / (3 - 1) = 0.6
Calculating global_avg:
subjectA
avg_sum
activity_count
day 1
0.5
1
day 3
2.3
3
day 6
2.6
5
subjectB
avg_sum
activity_count
day 4
0.8
1
day 6
1.8
2
global_avg (day 2 to 5) = (subjectA_avg + subjectB_avg)/2 = (0.6 + 0.8) / 2 = 0.7
I have hundred of subjects, so I need to now: Is there any way I could pre-process the subject_avgs so that I don't need to individually calculate its averages in the given time window before calculating global_avg?

How to calculate which second of song will be playing after x minutes of repeating?

I am not doing pretty well with algorithms, so I need your help :)
Case: I play a song that lasts 3 minutes 40 seconds at 1st August 00:00 (for example). How could I be able to calculate which second of the song will be playing after (again, for expample) 3 days, 7 hours, 3 minutes and 54 seconds or any other time interval?
Sorry if it sounds lame :(
That's a use case for the modulo operator, that gives the remainder of a division.
10 / 3 is 3 * 3 + 1. The +1 is the remainder
It's as simple as :
SecondOfTheSongCurrentlyPlaying = TotalSecondsElapsed % LengthOfTheSongInSeconds
In example, if the song lasts 3 minutes 40 seconds, this is 220 seconds.
3 days, 7 hours, 3 minutes and 54 seconds are 284 634 seconds.
284634 % 220 == 174 seconds

TiBCO Spotfire - How to Calculate only the last 3 columns in a Data - see descr

Week Sales
1 100
2 250
3 350
4 145
5 987
6 26
7 32
8 156
I wanted to calculate the sales only for the last 3 weeks so the total will be 156+32+26.
If new weeks are added it should automatically calculate only the data from the last 3 rows.
Tried this formula but it is returning an incorrect sum
sum(sales) over (lastperiod(3(week))
https://i.stack.imgur.com/6Y7h7.jpg
If you want only the last 3 weeks sum in calculated column you can use a simple if calculation.
If([week]>(Max([week]) - 3),Sum([sales]),0)
If you need 3 weeks calculation throughout table use below one.
sum([sales]) OVER (LastPeriods(3,[week]))

Calculating total days minus weekend

I have a requirement to obtain number of days passed since creation date. This number would need to minus the weekends. I have only some functions : JulianDay, JulianWeek, JulianYear to get Julian date values, I also have Today which returns the date of today, time stamp which returns date and time. I have manage to get the difference of today-creation date by using: JulianDay(today)-JulianDay(creation date) but I still can't wrap my head around subtracting the weekends
Not completely sure what the functions you cited in your question do, however, you seem to be comfortable with
doing the basic date arithmetic to determine the number of days between two given dates. The hard part seems
to be figuring out how may days to subtract for weekends.
I think you can accomplish this with two functions:
Given two dates, return the number of days between them. Call this DAYS(date-1, date-2)
Given a date, return the day of the week (where 1 = Monday ... 7 = Sunday). Call this DAY-OF-WEEK(date)
Having these functions you can then do the following:
Calculate full weeks in the date range: WEEKS = DAYS(date-1, date2) mod 7
Calculate days not parts of full weeks: DAYS-LEFT = DAYS(date-1, date-2) - (WEEKS * 7)
Determine which day of the week the last day falls on: LAST-DAY = DAY-OF-WEEK(date-2)
Adjust the number of DAYS-LEFT from the partial week as follows:
if DAYS-LEFT > 0 then
case LAST-DAY
when 6 then /* Saturday */
DAYS-LEFT = DAYS-LEFT - 1
when 7 then /* Sunday */
if DAYS-LEFT = 1 then
DAYS-LEFT = 0
else
DAYS-LEFT = DAYS-LEFT - 2
end-if
when other /* Monday through Friday */
case DAYS-LEFT - LAST-DAY
when > 1 then
DAYS-LEFT = DAYS-LEFT - 2
when = 1 then
DAYS-LEFT = DAYS-LEFT - 1
when other
DAYS-LEFT = DAYS-LEFT /* no adjustment */
end-case
end-case
end-if
DAYS-EXCLUDING-WEEKENDS = DAYS(date-1, date-2) - (WEEKS * 2) + DAYS-LEFT
I assume you have, or can build, a DAYS(date-1, date-2) function. The next bit is to determine what day of the week
a given date falls on. The algorithm to do this is called Zeller's congruence. I won't
repeat the algorithm here since Wikipedia does a fine job of describing it.
Hope this gets you on your way...
Your JulianDay(y,m,d) function returns a serial number for each date; let's say for the sake of discussion that JulianDay(2013,7,4) returns 2456478. The next day will be 2456479, then 2456480, and so on. And let's say that the difference of two days is diff.
The number of full weeks in diff, each containing 5 weekdays, is diff // 7 (that's integer division, so it rounds down). Thus if diff is 25, there will be 25 // 7 = 3 full weeks plus an extra diff % 7 = 4 days. The 3 full weeks contain 15 weekdays; it doesn't matter which day of the week you start from. So you only need to consider the 4 extra days to see how may are weekdays.
The number that the JulianDay function returns can be taken modulo 7 to calculate the day of the week; on my JulianDay function, modulo 5 represents Saturday and modulo 6 represents Sunday. You can take the 4 extra days to be either the 4 days at the beginning of the period or the 4 days at the end; it doesn't matter because all the other days are part of a period of consecutive full weeks that each have 5 weekdays. Say you pick the first 4 days. Then take the JulianDay of the first day modulo 7, then the JulianDay of the first day plus 1 modulo 7, then the JulianDay of the first day plus 2 modulo 7, then the JulianDay of the first day plus 3 modulo 7, determine how many of them are weekdays, and add that to the number of weekdays in full weeks.
All you need is a JulianDay function.
This code should do what you want:
Date fromDate = new Date(System.currentTimeMillis()-(30L*24*60*60*1000)); // 30 days ago
Date toDate = new Date(System.currentTimeMillis()); // now
Calendar cal = Calendar.getInstance();
cal.setTime(fromDate);
int countDays = 0;
while (toDate.compareTo(cal.getTime()) > 0) {
if (cal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY && cal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY)
countDays++;
cal.add(Calendar.DATE, 1);
}
System.out.println(countDays);

Algorithm to find nth working day [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have deviced a procedure to find nth working day without using loops.
Please bring around your suggesstions over this -
Algorithm to manipulate working days -
Problem: Find the date of nth working day from any particular day.
Solution:
Normalize to closest Monday -
If today(or the initial day) happens to be something other than monday, bring the day to the closest monday by simple addition or subtraction.
eg: Initial Day - 17, Oct. This happens to be wednesday. So normalize this no monday by going 2 dates down.
Now name this 2 dates, the initial normalization factor.
Add the number of working days + week ends that fall in these weeks.
eg: to add 10 working days, we need to add 12 days. Since 10 days has 1 week that includes only 1 saturday and 1 sunday.
this is because, we are normalizing to nearest monday.
Amortizing back -
Now from the end date add the initial normalization factor (for negative initial normalization) and another constant factor (say, k).
Or add 1 if the initial normalization is obtained from a Friday, which happens to be +3.
If start date falls on Saturday and sunday , treat as monday. so no amortization required at this step.
eg: Say if initial normalization is from wednesday, the intial normalization factor is -2. Hence add 2 to the end date and a constant k.
The constant k is either 2 or 0.
Constant definition -
If initial normalization factor is -3, then add 2 to the resulting date if the day before amortization is (wed,thu,fri)
If initial normalization factor is -2, then add 2 to the resulting date if the day before amortization is (thu,fri)
If initial normalization factor is -1, then add 2 to the resulting date if the day before amortization is (fri)
Example -
Find the 15th working day from Oct,17 (wednesday).
Step 1 -
initial normalization = -2
now start date is Oct,15 (monday).
Step 2 -
add 15 working days -
15 days => 2 weeks
weekends = 2 (2 sat, 2 sun)
so add 15 + 4 = 19 days to Oct, 15 monday.
end_date = 2, nov, Friday
Step 3a -
end_date = end_date + initial normalization = 4, nov sunday
Step 3b -
end_date = end_date + constant_factor = 4, nov, sunday + 2 = 6, nov (Tuesday)
Cross Verfication -
Add 15th working day to Oct, 17 wednesday
Oct,17 + 3 (Oct 17,18,19) + 5 (Oct 22-26) + 5 (Oct 29 - Nov 2) + 2 (Nov 5, Nov 6)
Now the answer is 6, Nov, Tuesday.
I have verified with a few cases. Please share your suggesstions.
Larsen.
To start with, its a nice algorithm, i have doubts about boundary conditions though: for example, what if i need to find the 0th working day from today's date:
Step 1 -
initial normalization = -2 now start date is Oct,15 (monday).
Step 2 -
add 0 working days -
0 days => 0 weeks
weekends = 0
so add 0 + 0 = 0 days to Oct, 15 monday.
end_date = 15, oct, monday
Step 3a -
end_date = end_date + initial normalization = 17, oct wednesday
Step 3b -
end_date = end_date + constant_factor = 17, Oct wednesday or 19,oct friday based on whether constant factor is 0 or 2 as it be only one of these values.
Now lets repeat the steps for finding the 1st working day from today:
Step 1 -
initial normalization = -2 now start date is Oct,15 (monday).
Step 2 -
add 1 working days -
1 days => 0 weeks
weekends = 0
so add 1 + 0 = 1 days to Oct, 15 monday.
end_date = 15, oct, monday
Step 3a -
end_date = end_date + initial normalization = 17, oct wednesday
Step 3b -
end_date = end_date + constant_factor = 17, Oct wednesday or 19,oct friday based on whether constant factor is 0 or 2 as it be only one of these values.
Did you notice, algorithm gives the same end result for 0 and 1. May be thats not an issue if t defined beforehand that 0 working days and 1 working days are considered as same scenario, but ideally they should be giving different results.
I would also suggest you to consider the negative test cases, like what if i need to find -6th working day from today, will your alforithm give me a date in past rightfully?
Lets consider 0th working day from today (17/10, wed).
Step 1 -
start_date = 17/10 wed
normalized date = 15/10 mon
Step 2 -
end_date = normalized date + working days
= 15/10 mon + 0 = 15/10 mon
Step 3 -
amortized_back = end_date_before_amortization + normalization factor
= 15/10 + (+2) = 17/10 wed
since the end_date_before_amortization falls on monday and initial normalization is 2, constant factor = 0.
hence, end_date = 17/10 wed.
now case 2, 1st working day from today.
Step 1 -
start_date = 17/10 wed
normalized date = 15/10 mon
Step 2 -
end_date = normalized date + working days
= 15/10 mon + 1 = 16/10 tue
Step 3 -
amortized_back = end_date_before_amortization + normalization factor
= 16/10 + (+2) = 18/10 thu.
since the end_date_before_amortization falls on tuesday and initial normalization is 2, constant factor = 0.
hence, end_date = 18/10 thu.
Looks to be working for 0th and 1st WD.

Resources