Convert date to week of year - algorithm

Given a date, is there an algorithm that can convert it to the week of the year?

Absolutely, but it gets very complicated.
In principle you should be able to divide by 60*60*24 = 86400 to get days, then follow the logic of the calendar to figure out days, weeks, years, and calculate the answer from that. There are 365 days in a year, except leap years. Leap years occur on years divisible by 4, except ones divisible by 100, but happen again on years divisible by 400. Since 2000 is divisible by 400, you can ignore the last 2 rules and you will be correct until the year 2100.
You also have to decide what a week is defined as. In the USA it is traditionally defined as Sunday through Saturday. In Europe it is traditionally defined as Monday through Sunday. But you know what day of the week 1970 started on (Thursday), and can therefore figure out the current year, what day of the week it started on, when that week started, and a little modulo 7 arithmetic gives you your answer.
That is...until you notice that actual date boundaries depend on timezone, whether daylight savings time is in effect, and other such things. This opens up a giant can of worms that everyone delegates to the Olson database. (Which itself needs multiple updates a year because some government, somewhere, tweaks their timezone rules.) And then every language and environment wraps their own date-time library around that. You are strongly advised to find and use that.
If time is represented in UTC, this is the end of the story. However in fact we also have leap seconds (27 so far, possibly a negative one coming soon). This is NOT dealt with by Olson or standard date-time libraries. All of whom try to find the most efficient way to ignore that the leap second happened, and pray that they don't crash when the next one comes. (Not a joke. Linux servers around the world crashed on Jul 2, 2012, and large companies have a variety of "time smearing" approaches to avoid it happening again.)
Only specialized tools like Frink deal with the ugliness of leap seconds in their full glory.

Assuming you already have the year, month, and day, here is the solution according to Pandas.
doy = get_day_of_year(year, month, day)
dow = dayofweek(year, month, day)
# estimate
iso_week = (doy - 1) - dow + 3
if iso_week >= 0:
iso_week = iso_week // 7 + 1
# verify
if iso_week < 0:
if (iso_week > -2) or (iso_week == -2 and is_leapyear(year - 1)):
iso_week = 53
else:
iso_week = 52
elif iso_week == 53:
if 31 - day + dow < 3:
iso_week = 1

Related

Simple algorithm to alternate days

I need to alternate between 2 tasks every day, and I need a simple algorithm to know which task I need to do.
I need to be able to run this algorithm by head, using simple general knowledge (like day of week, day of month, etc), and it must not rely of which task has been done the previous day (because I have a crappy memory).
I have tried checking for parity in a combination of day of week / day of month / # of month, etc, but couldn't find a suitable system: day of week have 2 consecutive odd numbers, same goes for day of month every so often.
I am afraid that this is impossible: if you can't remember what you did the day before, any other procedure will require more mnemonic effort.
remember what you did on January first (or another date),
remember the parities of the cumulated months: oeoeoeooeoe or ooeoeoeeoeo for a leap year,
add the cumulated parity of the month before* to the parity of the day,
add that to the parity of the first task.
E.g. if A on January 1st 2022, then on March 17, 2022: e + o = o gives B.
*In January, use even.
You can also state the month parity rule as: until August inclusive, use the co-parity of the month number; then use the parity. But for a leap year, change that parity after February (excluded).
I need to be able to run this algorithm by head
So, you don't need to take help of Computer science. You can use cognitive human ability to map a thing to another thing.
Note: This need not make sense to everybody though, if you are thinking out of the box.
Map task 1 as God's day.
Map task 2 as Devil's day in your brain.
This should be simple just like day and night.
Now, remember that devil's evil karma is always burnt by God the next day and that devil never learns his lesson. So this way, alternating would be easy.
Friends Episode snippet on Youtube
Just count the number of days in between your date and a given "zero" one...then use parity.
Take number of seconds (or milli, or whatever) since EPOCH (common zero for date and time), divide (integer division) by 60x60x24 (or 1000x60x60x24, or what is appropriate), you then get the number of days since EPOCH.
----EDIT----
Example: Got 1653910695 seconds since EPOCH (at the time of my experience). Dividing it by 60x60x24 give 19142 days. To morrow it will give 19143, etc.
<?php
$day = Date('j');
$previous_day = date('j', strtotime("-1 days"));
if($day%2==0 OR $previous_day%2!=0)
echo "Task 1";
}else{
echo "Task 2";
}
?>

algorithm: get next year date work shift type according week number

I work in 3 shifts, each week different one. The order is morning shift (m), night one (n) and afternoon one (a). The order i fixed, i.e. it never changes, even if one won't work that week.
I created a function to get ISO week number. When I throw it a date, it returns week number.
This week (no. 48), for example, I work morning, therefore 48 % 3 = 0 → m = 0; n = 1; a = 2.
I saved this into array shifts = ["m", "n", "a"].
This is the easy part. But as the end of the year comes, I need to solve a problem. As 52 (the total number of weeks in 2017) is not divisible by 3 and there are different number of weeks in different years, modulo 0 (which for year 2017 means m), means something else in different years.
So, the actual question is what would be the fastest and simplest algorithm (rather fastest than simplest), doesn't need to be human-readable, with explanation (if necessary) why/how does it do what it does.
I thought of one (which is neither fast nor simple): to the known week no. & shift type combo add the number of weeks following that week until the end of the year, and recalculate the array shifts.
Why do you want to use ISO week numbers ?
Let's say that your weeks start on some specific day (monday, sunday, you decide). You decide of a starting date d0, also a week start, for shift 0. Then for any date d your shift is:
shift = floor(nbdays(d - d0) / 7) mod 3
Problems may arise if your system work in different locales where the starting day for a week is not the same. In that case you should have a specific d0 for each locale. If your shift is the same worldwide you have no problem.

How to add a simple calendar to my windows store app

I'm working on a Universal windows store app and I want to add a simple calendar so that users can add birthdays of their friends and save them and some other stuff. Is there any simple way to do this?
PS: Using Visual Studio 2013
What I do understand about Calendars, is there are fourteen of them in total that are possible - seven for each day of the week a normal year begins on, and seven more for leap years. You may have to create all fourteen and put them in somehow. There is instead a formula for working out what day of the year anyone was born on by their date of birth, and formulae can be programmed into r or other programmes using perhaps the for loop, or if command. This formula is :
{4(d+y)+x-4c}/28, where d is what number day of the year it is - so Jan 1st, d=1, and so on, but for Leap Years it gets different from Feb 29, y is the year in question, x the closest year before y divisible by four, and c an era constant. For modern dates, c=0, so no worries, but if You go back before September, 1752, it changes, as this is when the British went from the Julian to the Gregorian, while in Catholic Europe it was October, 1582, but these are only a concern if You are into such historical dates. For those, c=1, but may have different values much earlier - if You want to know more, reply to this, and I will get out what I have written on it.
For example, if one was born on 17th May, 1979, you would go :
{4(137+1979)+1976-4 times zero}/28, which equals 372 plus six sevenths - you ignore the whole number, and look at how many sevenths there are. Six means Thursday, and thus the 17th May, 1979 was a Thursday. This is it in short - for more details, if this interests, feel free.
The simple way is in use third-party controls like Telerik Calendar or something free like this one.

Slight problem with day of the week calculation (base doomsday for a century)

From this online calculator: http://homer.freeshell.org/dd.cgi using its data I've successfully written a working version, however its data is limited to years 1500 to 2600. I want to modify (and make a better one) so that I can calculate for any year > 2600.
Referring to Table X, is there actually a formula to calculate the base doomsday for all base centuries (above 2600)?
I've tried working it out myself by putting centuries higher than this e.g. 2700 gave me a base doomsday of '00', 2800 gave '02;, 2900 back to '00' again...
Help appreciated.
As I understand it, that page's “Base Doomsday” is just an offset to allow for the four-hundred-year cycle of leap day calculations. So, you can extend it indefinitely into the future simply by adding blocks of four centuries.
Are there any other calculators out there that do this?
Two common methods for calculating the day of the week
given a date are Doomsday, which you are using,
and Zeller's Congruence
www.merlyn.demon.co.uk provides
some really interesting information on date/time calculations, various calendar
systems and significant dates as they relate to calendar/date calculations.
The calculator at this link http://homer.freeshell.org/dd.cgi is the best in terms of explaining doomsday algorithm cleanly and clearly for human, with one little caveat.
If you input 2/29/1900, it would say it's a Thursday. Well, there is no 2/29/1900, because it's not a leap year.
Of course if your input 1/35/2016, it would "garbage-in-garbage-out" for you as well.
Imagine there are only 364 days in a year, then the day of week for each date will never change year after year, because mod(364,7)==0.
But we have 365 days a year, so the day steps forward 1 each year, that's where the second term mod(year, 7) comes from.
In addition, every 4 year, there is a leap year, which contributes to the last term mod(year, 4).
But every 100 years, you subtract a leap year, and every 400 years, you add one leap year. That's where the first term "3,2,0,5" comes in.
You see, it's all because of this leap year, and mod(365,7)==1 business.
7/11, 5to9 helps to remember table Z greatly.

Identify years with identical days of the week (e.g. 1994, 2005, 2011)

I have an idea for a story in which certain events happen repeatedly throughout the year of calendar dates that perfectly match each other for example 2011, 2005, 1994 one could replace these calendars with each other
I would like to be able to find calendar years past and future
If someone could help me please as I have no programming ability
Thanks in advance
Check Wikipedia.
You only need to compare the day of the week on which the first day of the year falls, and compare leap years and non-leap years separately (they will obviously differ). If the first day is the same and the days in the year are the same, so will the whole year be the same.
With this reduction, we need to first know what is a leap year. From wikipedia, the algorithm is
if year modulo 400 is 0
then is_leap_year
else if year modulo 100 is 0
then not_leap_year
else if year modulo 4 is 0
then is_leap_year
else
not_leap_year
Then we need to calculate the first day of the year. Before we start, we need a grounding. Let's take 2000, which starts on a Saturday. Every year we move forward, we move forward one day in the week except if the year follows a leap year in which case we move forward two days.
Let's walk through an example. 2000 starts on Saturday. 2001 starts on a Monday, 2 days later because 2000 is a leap year. 2002 starts on Tuesday. 2003 on a Wednesday. 2004 on a Thursday. 2005 on a Saturday, because 2004 is a leap year. From this we see that 2000 and 2005 start on the same day of the week, but the one is a leap year while the other is not. If we continue we'll find 2011 starts on a Saturday, and is therefore identical to 2005.
We can work backwards in similar fashion to find years in the past, or we can just choose an earlier starting year.
Dominical letter B: ... 1910 1921 1927 1938 1949 1955 1966 1977 1983 1994 2005 2011 2022 2033 2039 2050 2061 2067 2078 2089 2095 ...
Be careful about going back before 1752 and 1582, where 11 and 10 days were dropped from the calendar, respectively. see dataandtime.com. Otherwise there are exactly 14 possible calendars ... Half with a Feb 29th, half without. Each pair of calendars starts on a different day of the week. There should be an excel spreadsheet out there (its easy enough to generate one) that maps the years since 1752 into one of 14 columns.
2016 ends on the same days of the week as 1994, 2005 and 2011, but 2016 starts on Friday (leap year), while all the other years start on Saturday, therefore we need to wait until 2022 before the dates in 2011 match up again.

Resources