Trouble with a multiple condition when statement in CoffeeScript - coffeescript

In Finland, like in many countries, we have name days for different names.
I'm trying to write an Ubersicht app to display the day of the year, and the name of that day.
I've brought in the Day of the Year (%j) and Year (%Y), split them so I can manipulate them, and have found a way to find a leap year in CoffeeScript.
However, because leap years have an extra day, the 29th Feb is not a name day (along with 1st Jan and 25th Dec), so I want to display "No names today!" on those days, both when it is, and isn't, a leap year.
command: "date +%j,%Y"
update: (output) ->
dateString = output.split(',')
yearday = parseInt(dateString[0])
year = dateString[1]
leapyear = (year % 400 == 0) or (year % 4 == 0 && year % 100 != 0)
# The Switch statement
yearday = switch
when (leapyear and yearday is [1, 60, 360]) then "No names today!"
else
when yearday is 2 then " Aapeli "
when yearday is 3 then " Elmer, Elmo "
when yearday is 4 then " Ruut "
... and so on
The problem I'm having is that I'm getting an ParseError: 'unexpected when'.
I'm pretty new to building widgets (I have an idea how I would do this in Python), and I'm having some difficulty with my switch statement.
I have also tried bringing in the month day (%d) and month number (%e), but I ran into similar issues there (multiple when conditions e.g. when month = 3 and day = 5 (for 5th May) not working).
Any help would be greatly appreciated. As I said, I'm new to CoffeeScript, so explanations would be greatly appreciated as well.

You might want to reread switch syntax
yearday = switch leapyear
when 2 then 'Aapeli'
when 3
if additional_conditionals then A else B
when 4 then 'Ruut'
else 'No names today!'
# else is default, you can't nest additional when statements here
However, the simpler solution would be to use an array instead.
(This is not quite about Coffeescript but applies to thinking about programming in general.)
dayNames = ['', '', 'Aapeli', 'Elmer, Elmo', 'Ruut']
dayName = (day) => switch day
when 0 then 'fails, no 0th day' # optional
when 1, 60, 360 then 'No names today!'
else "Name of day #{day} is #{dayNames[day]}."
# Additionally, don't prewrite the spaces.
# Use string manipulation like above instead
# (note the difference between single and double quotes)
console.log dayName 4
# 'Name of day 4 is Ruut.'
console.log dayName 60
# 'No names today!'
(Btw please remove extra info about Finland days, it's just irrelevant..)
Cheers :)

Related

how to check if a number is whole number or contains a decimal

If a number is 2017 and I divide it by 4, I get 504.25.
if the number is 2016 an I divide it by 4, I get 504.
My question is, is there a way to use perl to check if a number that was divided, if the answer is a whole number and has NO decimal at all?
UPDATE: I got it working from the answer I selected below. I was trying to check if this is leap year, because today my code broke, because my code ran from the cron job as set to run on the last day of every month. Typically for feb, that is the 28th, so it ran on the 28th and shut the website done for the end of month maintenance. so what I have it do now is run on both Feb 28th and Feb 29th (For if there is a 29th) and in the code, I have it check if it is leap year now like this:
my $_leapNum = 4; # Leap year is always divisible by 4 with no remainder...
my $_NotLeapRemain = $_lTimeYYYY % $_leapNum; # I have $_lTimeYYYY built for the year only - longyear
if($_NotLeapRemain) {
my $_isLeapYear = 0;
} else {
my $_isLeapYear = 1;
}
Then later I check if it is leap year. If it is, then I check if the day is 28th, if it is, then it just exits. If it is the 29th, then it does what it was intended to do.
I tested it and it works perfectly now.
Thank you for your help.
-Rich
If you want to know if the result of dividing a $dividend by a $divisor is going to be a whole number or a number with a fractional portion, you can test that condition first:
if (my $remainder = $dividend % $divisor) {
print "$dividend cannot be divided evenly by $divisor.",
" There is a remainder of $remainder.\n";
}
else {
print "$dividend is evenly divisible by $divisor,",
" and the result is ", $divident / $divisor, "\n";
}
*EDIT: * This answer was posted in response to the original, un-edited question, which asked how to determine if the result of division contains a decimal portion. Now that the sense of the question changed toward date math, I agree that a DateTime solution is much better.

What do the correct arguments for Date dayMonthYearDo: look like in Smalltalk (Pharo / Squeak)

Date dayMonthYearDo: aBlock
"Supply integers for day, month and year to aBlock and return the result"
^ start dayMonthYearDo: aBlock
What should a typical valid block look like for this message?
In this case the comment "Supply integers, etc." means that the argument aBlock will receive three integers as "actual" arguments: day number, month index and year. This means that you will have to create a block with three "formal" arguments, say, day, monthIndex and year as in:
aDate dayMonthYearDo: [:day :monthIndex :year | <your code here>]
The code you write inside <your code here> can refer to the "formal" parameters day, monthIndex and year, much as if it was a method with these three arguments.
This is how blocks generally work in Smalltalk.
Example
aDate
dayMonthYearDo: [:day :monthIndex :year |
monthIndex + day = 2
ifTrue: [Transcript show: 'Happy ' , year asString, '!']]
UPDATE
The example above checks for January 1st by "ingeniously" comparing monthIndex + day with 2. In fact, since both variables are >= 1 the only way to get 2 is when day and monthIndex are both 1, i.e., when the receiver aDate is January 1. A more "serious" approach would look like
(monthIndex = 1 and: [day = 1]) ifTrue: [ <etc> ]
Something like this:
Date today dayMonthYearDo: [:d :m :y| Transcript cr;
show: 'today is the ';
show: d;
show: 'th'
]
today is the 28th
But of course you may do different things that just showing things on transcript

Setting up a two week timetable in Swift

NOTE: I am a new Swift programmer, a NOOB if you will.
I am creating a school timetable app just for personal use to practise my coding. However, our school operates on a two week time table system, with 10 days, labeled 1 through to ten. I am wondering if anyone had some ideas as to how I could work out whether the current date is day one or day nine or day 4. I know I could use if statements for the dates, but the would take a long time, and require manual input of the dates. How could I have the app keep count of what day it is, skipping weekends?
EDIT - I could maybe have 14 days, with days 6,7,13 and 14 empty.
FOR EXAMPLE:
The current date is OCT 4, this is day one. I would like the app to be able to work out what day of the timetable the current date is. This would then load the appropriate day (e.g. Subject, Teacher, Classroom). Day One is Monday, Two is Tuesday, Five is Friday, Six is Monday, 10 is Friday. Could I have some sort of rostering system?
I am sorry if the question is vague, please tell me if I need to clarify.
I have been working on a fix for weeks now, so I have decided to turn to help. Any guidance whatsoever would be much appreciated, as I am at a dead end!
Many thanks
The numbers that I'm plugging into this example probably don't match your requirements but consider this as a strategy. (In this case, using a 1-to-14 cycle. If you'd rather get 1-to-10 you can put in a subtraction and a different error to throw on the "bad" days.)
class CyclicDay {
enum CyclicDayError: ErrorType {
case InvalidStartDate
}
lazy var baseline: NSDate? = {
// Set up some start date that matches day 1
var components = NSDateComponents()
components.day = 6
components.month = 9
components.year = 2015
return NSCalendar.currentCalendar().dateFromComponents(components)
}()
func dayOfCycle(testDate: NSDate) throws -> Int {
if let start = baseline {
// Convert difference to days
let interval = testDate.timeIntervalSinceDate(start)
let days = interval / (60 * 60 * 24)
// Convert to value 1..14 to position in a 2-week cycle
return Int(days % 14) + 1
}
throw CyclicDayError.InvalidStartDate
}
}
// Test today
let cd = CyclicDay()
let day = try cd.dayOfCycle(NSDate())

How to loop through a date range in which dates are stored as Integers?

I have to develop a system, where user will specify a starting range and an ending range (By Range, I mean to say a particular period, where PERIOD is given as a concatenation of YEAR AND MONTH). For example, PERIOD = 201304, where 2013 is the user entered Year and 04 is the MONTH. The user can specify a maximum range of upto 2 years only.
Data needs to be selected on the basis of the user entered range. The problem is whenever I try to loop through the period, the PERIOD changes after 201312 to 201313. I have separate variables for user selected year and month (start_year, start_month, end_year, end_month)
I did a IF loop there in which I tried to do the following
FOR p_tmpyear = p_tempfrom TO p_tempto
IF (p_monthfrm < 12) THEN
LET p_yearfrm = p_yearfrm + 1
LET p_monthfrm = 01
LET p_fromperiod = p_yearfrm + 1,p_monthfrm >p_fromperiod is an integer storing concatenated Month and Year, to achieve the desired PERIOD format as mentioned above.
LET p_tempfrom = p_fromperiod
END IF
DISPLAY p_tmpyear
END FOR
I even tried thsi one :
IF (p_fromperiod MOD p_yearfrm = 13) THEN
LET p_yearfrm = p_yearfrm + 1
LET p_monthfrm = 01
LET p_fromperiod = p_yearfrm + 1,p_monthfrm
Still the period changes after reaching 201212 to 201213. I want this to be 201301. Please help.
As you have probably guessed, you have some flaws in your logic. The first example is too hard to decipher, whilst the second shows you don't understand what the MOD operator does. If used correctly, in this context, it would be of the form IF variable MOD 12 = 0 i.e. every 12th value do something.
I think where you are going wrong is trying to do it all in one loop. I would keep it simple and break the problem into two nested loops, one for year, one for month
DEFINE start_year, end_year, start_month, end_month INTEGER -- sample values 2012, 2013,7,6
DEFINE loop_year, loop_month INTEGER -- values used to loop through year and month respectively
DEFINE loop_first_month, loop_last_month INTEGER -- for each year, calc first month and last month
DEFINE period CHAR(6)
-- First loop over year
FOR loop_year = start_year TO end_year
-- Calculate first and last month for the given year
-- If first year, use passed in start month else use 1
IF loop_year = start_year THEN
LET loop_first_month = start_month
ELSE
LET loop_first_month = 1
END IF
-- If last year, use passed in end month else use 12
IF loop_year = end_year THEN
LET loop_last_month = end_month
ELSE
LET loop_last_month = 12
END IF
-- Second loop over month
FOR loop_month = loop_first_month TO loop_last_month
LET period = loop_year USING "&&&&",loop_month USING "&&"
DISPLAY period
END FOR
END FOR
I would also encourage you to also post questions like this in the dedicated 4Js Genero developers forum at the 4Js website http://www.4js.com/fjs_forum/ as well as here. Most Genero developers should be aware of that forum and have access.

Unix gettimeofday() - compatible algorithm for determining week within month?

If I've got a time_t value from gettimeofday() or compatible in a Unix environment (e.g., Linux, BSD), is there a compact algorithm available that would be able to tell me the corresponding week number within the month?
Ideally the return value would work in similar to the way %W behaves in strftime() , except giving the week within the month rather than the week within the year.
I think Java has a W formatting token that does something more or less like what I'm asking.
[Everything below written after answers were posted by David Nehme, Branan, and Sparr.]
I realized that to return this result in a similar way to %W, we want to count the number of Mondays that have occurred in the month so far. If that number is zero, then 0 should be returned.
Thanks to David Nehme and Branan in particular for their solutions which started things on the right track. The bit of code returning [using Branan's variable names] ((ts->mday - 1) / 7) tells the number of complete weeks that have occurred before the current day.
However, if we're counting the number of Mondays that have occurred so far, then we want to count the number of integral weeks, including today, then consider if the fractional week left over also contains any Mondays.
To figure out whether the fractional week left after taking out the whole weeks contains a Monday, we need to consider ts->mday % 7 and compare it to the day of the week, ts->wday. This is easy to see if you write out the combinations, but if we insure the day is not Sunday (wday > 0), then anytime ts->wday <= (ts->mday % 7) we need to increment the count of Mondays by 1. This comes from considering the number of days since the start of the month, and whether, based on the current day of the week within the the first fractional week, the fractional week contains a Monday.
So I would rewrite Branan's return statement as follows:
return (ts->tm_mday / 7) + ((ts->tm_wday > 0) && (ts->tm_wday <= (ts->tm_mday % 7)));
If you define the first week to be days 1-7 of the month, the second week days 8-14, ... then the following code will work.
int week_of_month( const time_t *my_time)
{
struct tm *timeinfo;
timeinfo =localtime(my_time);
return 1 + (timeinfo->tm_mday-1) / 7;
}
Assuming your first week is week 1:
int getWeekOfMonth()
{
time_t my_time;
struct tm *ts;
my_time = time(NULL);
ts = localtime(&my_time);
return ((ts->tm_mday -1) / 7) + 1;
}
For 0-index, drop the +1 in the return statement.
Consider this pseudo-code, since I am writing it in mostly C syntax but pretending I can borrow functionality from other languages (string->int assignment, string->time conversion). Adapt or expand for your language of choice.
int week_num_in_month(time_t timestamp) {
int first_weekday_of_month, day_of_month;
day_of_month = strftime(timestamp,"%d");
first_weekday_of_month = strftime(timefstr(strftime(timestamp,"%d/%m/01")),"%w");
return (day_of_month + first_weekday_of_month - 1 ) / 7 + 1;
}
Obviously I am assuming that you want to handle weeks of the month the way the standard time functions handle weeks of the year, as opposed to just days 1-7, 8-13, etc.