Python Function for Year, Month, Date & return Day - python-3.7

I have written following Python Function which should return Day, when year, month & date is provided to function. For Testing, I have limit it to 3 years & then call the function using print. But it always return “Saturday”. What’s wrong in function.
enter code here
def dayOfYear(y,m,d):
if y in [2018,2019,2020]:
if m in [1,2,3]:
if d in [31,28,1]:
return('Saturday')
else:
return('Thursday')
else:
return('Sunday')
else:
return(None)
print(dayOfYear(2018,1,31))
print(dayOfYear(2019,2,28))
print(dayOfYear(2020,3,1))

Related

If-Else-Then with today()

i am currently trying to write some code that goes through my data and marks a number 0-12 based off the date in the "Week" column. this number appears in a new column called group which is created by the code you see below. The problem is that this column is periods all the way down and not numbers. There are no errors messages in the log so i dont know where i went wrong (im fairly new to sas). PS. the dates range from 6/17 to 9/9
data have;
set have;
if today()+84 = Week > today()+79 then group=12;
else if today()+77 = Week > today()+72 then group=11;
else if today()+70 = Week > today()+65 then group=10;
else if today()+63 = Week > today()+58 then group=9;
else if today()+56 = Week > today()+51 then group=8;
else if today()+49 = Week > today()+45 then group=7;
else if today()+42 = Week > today()+37 then group=6;
else if today()+35 = Week > today()+30 then group=5;
else if today()+28 = Week > today()+23 then group=4;
else if today()+21 = Week > today()+16 then group=3;
else if today()+14 = Week > today()+11 then group=2;
else if today()+7 = Week > today()+2 then group=1;
else if today() = Week > today()-5 then group=0;
run;
update:
the first column is called week and is a monday date that goes 12 weeks into the future. the rest of the columns are variables that i will end up summing based on the group that row is in.
ex:
week ID var2 ... var18
17jun2019 1 x x
24jun2019 1 x x
and it continues until 09sept2019.. it does this for each ID (roughly 10,000 of them) but not every id goes 12 weeks out thats why i am using the else if
i would like it to look like
week ID var2 ... var18 group
17jun2019 1 x x 0
24jun2019 1 x x 1
01july2019 1 x x 2
A full reference to SAS operators can be found in SAS help by searching SAS Operators in Expression. SAS expressions can use some operators that are relatively unique across the spectrum of coding languages. Here are some that are not typically found in newly coded SAS (at time of this post)
<> MAX operator
>< MIN operator
implied AND operator
Two comparisons with a common variable linked by AND can be condensed with an implied AND.
So the uninitiated readers of the question may misunderstand
…
if today()+35 = Week > today()+30 then group=5;
…
as incorrect, instead of recognizing it as an implied AND
…
if today()+35 = Week AND Week > today()+30 then group=5;
…
When syntactically correct, the = in the implied AND causes the expression to be true only on equality. The week value in open interval ( today()+35, today()+34 ) will never evaluate as true in the above expression. This is the likely cause of the missing values (.) you are seeing.
Why does the code exhibit non-static delta of 7 in the sequence 30,23,16,11,2,-5 ?
Should it be 30,23,16,9,2,-5.
In other words why is group 1 apparently shooting for a 5 day range [+7, +2) when all the others are 3, such as [+14, +11) ?
Why are there 2-days domains, presumed weekends, in which group is not assigned, and would thus be missing (.) ?
This type of wallpaper code is often better represented by a an arithmetic expression.
For example, presuming integer SAS date values:
group = ifn ( MOD (week-today(), 7) in (1,2)
, .
, CEIL (week-today() / 7 )
);
if not ( 0 <= group <= 12 ) then group = .; * probably dont want this but makes it compliant with OP;
Tomorrow the group value could 'wrong' because it is today() based. Consider coding a view instead of creating a permanent data set -- OR -- place meta information in the variable name group_on_20190622 = …
If you insist on wallpaper, consider using a select statement which is less prone to typing errors that can happen with errant semi-colons or missing elses.
It is not at all clear what you are trying to do. It sounds a little like you want to group observations based on how many weeks the date variable (called WEEK) is away from today's date. It might be easiest to just use the INTCK() function. That will count how many week boundary's are crossed between the two dates.
data have ;
input id week date9.;
format week date9.;
cards;
1 17jun2019
1 24jun2019
1 01jul2019
2 24jun2019
2 01jul2019
2 08jul2019
;
data want ;
set have;
group = intck('week',today(),week);
run;
You can then summarize the number of ID's per group.
proc freq data=want;
tables group;
run;
Results:
The FREQ Procedure
Cumulative Cumulative
group Frequency Percent Frequency Percent
----------------------------------------------------------
-1 1 16.67 1 16.67
0 2 33.33 3 50.00
1 2 33.33 5 83.33
2 1 16.67 6 100.00
Assuming week is date and not datetime.
data test;
do i = 1 to 30;
dt = intnx('day',today(),1*i);
output;
end;
format dt date9.;
run;
data test2;
set test;
if dt ge today() and dt le today()+7 then dt2 = 1;
else if dt ge today()+8 and dt le today()+14 then dt2 = 2;
else if dt ge today()+15 and dt le today()+21 then dt2 = 3;
else if dt ge today()+22 and dt le today()+28 then dt2 = 4;
else if dt ge today()+29 and dt le today()+35 then dt2 = 5;
/* another way */
dt3 = ceil(intck('day',today(),dt)/7);
run;
removed wrong answer.

A code which computes which is the nth day of the year

I want to write a matlab code to get which day is the first day of year and also get n and display which is the nth day of that year.
And also i don't know why it can not compare a(for example sat) and w(i)
(W=[sat,sun,....,fri]
Please help me I really can't make it work!
This is what I have done so far:
First=input('sat,sun,...,fri');
day=('a number between 1and 365');
day=mod(day,7);
w=[sat,sun,....,fri];
for i=1:7
if first==w(i)
disp(mod(i+day,7))
end
end
Note the syntax in the code below. I noticed you had quite a lot of errors in your syntax. Also, I recommend you use datenumand datestr as in the code below. Run help datenum and help datestr to get more information about the functions.
% User selects a year as a double
year = input('Select a year: ');
% the first day of that year as a value
date = datenum([num2str(year),'-01-01']);
% Get the name of the first day and diplay it
first = datestr(date,'dddd');
disp(['The first day of ', num2str(year), ' was a ', first])
% get nth day from user
day = input('Choose a number between 1 and 365: ');
% Add this value to the value of 1st jan on the selected year
newDate = date + day-1;
% Turn this date into a string and display it
nth = datestr(newDate,'dddd-dd-mmmm');
disp(['Day ', num2str(day),' of ', num2str(year), ' was ', nth])

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

Vectorising Date Array Calculations

I simply want to generate a series of dates 1 year apart from today.
I tried this
CurveLength=30;
t=zeros(CurveLength);
t(1)=datestr(today);
x=2:CurveLength-1;
t=addtodate(t(1),x,'year');
I am getting two errors so far?
??? In an assignment A(I) = B, the number of elements in B and
Which I am guessing is related to the fact that the date is a string, but when I modified the string to be the same length as the date dd-mmm-yyyy i.e. 11 letters I still get the same error.
Lsstly I get the error
??? Error using ==> addtodate at 45
Quantity must be a numeric scalar.
Which seems to suggest that the function can't be vectorised? If this is true is there anyway to tell in advance which functions can be vectorised and which can not?
To add n years to a date x, you do this:
y = addtodate(x, n, 'year');
However, addtodate requires the following:
x must be a scalar number, not a string.
n must be a scalar number, not a vector.
Hence the errors you get.
I suggest you use a loop to do this:
CurveLength = 30;
t = zeros(CurveLength, 1);
t(1) = today; % # Whatever today equals to...
for ii = 2:CurveLength
t(ii) = addtodate(t(1), ii - 1, 'year');
end
Now that you have all your date values, you can convert it to strings with:
datestr(t);
And here's a neat one-liner using arrayfun;
datestr(arrayfun(#(n)addtodate(today, n, 'year'), 0:CurveLength))
If you're sequence has a constant known start, you can use datenum in the following way:
t = datenum( startYear:endYear, 1, 1)
This works fine also with months, days, hours etc. as long as the sequence doesn't run into negative numbers (like 1:-1:-10). Then months and days behave in a non-standard way.
Here a solution without a loop (possibly faster):
CurveLength=30;
t=datevec(repmat(now(),CurveLength,1));
x=[0:CurveLength-1]';
t(:,1)=t(:,1)+x;
t=datestr(t)
datevec splits the date into six columns [year, month, day, hour, min, sec]. So if you want to change e.g. the year you can just add or subtract from it.
If you want to change the month just add to t(:,2). You can even add numbers > 12 to the month and it will increase the year and month correctly if you transfer it back to a datenum or datestr.

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.