counting the days since 1600/1/1

Joel
Posts: 57
Joined: Fri Jan 15, 2016 1:36 pm
My devices: miniipad
Flag: Germany

counting the days since 1600/1/1

Post by Joel »

Hi there,
For date calculations I needed a program to calculate the number of days since 1/1/1600. This program can also be used to calculate the difference between two dates, for example.

Code: Select all

INPUT year, month,day
PRINT days_1600(year,month,day) 'calculates the number of days since 1600/1/1

'c'

DEF days_1600(year,month,day)
'set leapyear (is this year a leapyear? and count leap years since 1600
leaps=leaps2(year)
IF year=1600 THEN 
 leapyear=1 
ELSE 
 IF leaps2(year-1)=leaps THEN 
  leapyear=0 
 ELSE 
  leapyear=1
 ENDIF
ENDIF

dyear=year-1600
IF NOT num_in_range(month,1,12) THEN RETURN -1'valid input?
IF NOT num_in_range(day,1,31) THEN RETURN -1 'upper limit will be checked later
RESTORE
result=0
 FOR days_in_month=1 TO month-1
  READ days
  result=result+days 'sum up all days of prev month
 NEXT days_in_month
 result=result+day 'add the input day
 READ days 'for validity purpose
 IF month=2 AND leapyear THEN days+=1 'days will not longer be used so this is for next line
 IF days<day THEN RETURN-1 'invalid date
 result=result+dyear*365+leaps 'add days of prev years and number of leap years
 IF month<=2 AND leapyear THEN result-=1 'in jan or feb ignore the this year leap status 
 RETURN result
 DATA 31,28,31,30,31,30,31,31,30,31,30,31
END DEF

DEF num_in_range(num, num1,num2)
 IF num<num1 OR num>num2 THEN RETURN 0 ELSE RETURN 1
END DEF

DEF leaps2(year)
 dyear=year-1600
 each4=FLOOR(dyear/4)
 each100=FLOOR(dyear/100)
 each400=FLOOR(dyear/400)
 result=each4-each100+each400+1'1600 is a leap year itself
 RETURN result
END DEF

User avatar
Dutchman
Posts: 851
Joined: Mon May 06, 2013 9:21 am
My devices: iMac, iPad Air, iPhone
Location: Netherlands
Flag: Netherlands

Re: counting the days since 1600/1/1

Post by Dutchman »

There is a calendar function-library and several calendar programs on dropbox
See https://www.dropbox.com/sh/1xc3n6mrs4sk ... BqP7a?dl=0
See also viewtopic.php?f=20&t=556
The program that I use once a year is "Party Calendar" which calculates special days for a party during a year :D
The program "Date Calculator", with input 16000101 20171002 gives the following output:
16000101 to 20171002.PNG
16000101 to 20171002.PNG (86.93 KiB) Viewed 6372 times
Last edited by Dutchman on Thu Jan 19, 2023 3:20 pm, edited 1 time in total.

Joel
Posts: 57
Joined: Fri Jan 15, 2016 1:36 pm
My devices: miniipad
Flag: Germany

Re: counting the days since 1600/1/1

Post by Joel »

wow, thats great!! didn't know that...that would have saved me the waste of an afternoon.
thank you very much... I'll take a closer look at it right away.
I am, by the way, glad that the results are identical. In my case, the days from 1.1.1600 are counted, while in your case the difference days are counted. Hence the difference of one day.

User avatar
Dutchman
Posts: 851
Joined: Mon May 06, 2013 9:21 am
My devices: iMac, iPad Air, iPhone
Location: Netherlands
Flag: Netherlands

Re: counting the days since 1600/1/1

Post by Dutchman »

I propose to subtract 1 from the result of your program.
If you enter the second of January 1600 in your program then the result is 2.
I think that most people don't agree that from the first of January to the next day equals a period of two days :lol:

Joel
Posts: 57
Joined: Fri Jan 15, 2016 1:36 pm
My devices: miniipad
Flag: Germany

Re: counting the days since 1600/1/1

Post by Joel »

Hello Dutchman,
thank you very much for your advice!
For me, it's just a matter of definition. The calendar of my program begins on first of January 1600 (that's just to make it easier to calculate the leap years). Thus January 1st of 1600 is the first day(=1), January 2nd the second day(=2), and so on.
In other applications, such as calculating the difference days (interval period) between two specified dates, this peculiarity disappears anyway:
For example, if you subtract January second of 1600 (=2) from the first of 1600 (=1), the result is indeed one.
(The same applies to the calculation of the weekday of a specified date. Here it is a simple modulo division that leads to the same result on the basis of the weekday of January first 1600.)

User avatar
Dutchman
Posts: 851
Joined: Mon May 06, 2013 9:21 am
My devices: iMac, iPad Air, iPhone
Location: Netherlands
Flag: Netherlands

Re: counting the days since 1600/1/1

Post by Dutchman »

I understand, it is the daynumber since the beginning of the year 1600. ;)

Joel
Posts: 57
Joined: Fri Jan 15, 2016 1:36 pm
My devices: miniipad
Flag: Germany

Re: counting the days since 1600/1/1

Post by Joel »

Yes, I think that's precisely what it is.;-)

User avatar
GeorgeMcGinn
Posts: 435
Joined: Sat Sep 10, 2016 6:37 am
My devices: IPad Pro 10.5in
IMac
Linux i386
Windows 7 & 10
Location: Venice, FL
Flag: United States of America
Contact:

Re: counting the days since 1600/1/1

Post by GeorgeMcGinn »

POST EDITED: I had the wrong code pasted into the post. It has been replaced.

Joel,

As someone who works in cosmology, astronomy and physics, the formula for calculating leap years is a very simple one.

However, looking at your code, why are you using FLOOR instead of MOD? In SmartBASIC, the MOD function is "%". X=405%360 returns X=45, 45 the remainder of 405/360.

MOD function in SmartBASIC's manual has half a sentence, if that, and I missed it many times, until I asked in a post if SB had a MOD function.

I would like to see a small section dedicated to the MOD, and Ton, you can use my code below to use as an example of one way to use it. I can write up more on it with other examples if your wish. Let me know.

The problem with using FLOOR or CEIL or any of the other math functions is you may get rounding errors, and could flag a year as a leap year or one that is a leap year as not one, and your calendar is off.

Here is a simple program using the SB MOD function that can be easily changed to a function, and returning switched values, tell you if a year is a Leap Year or not. No need to provide it with a table of valid Century years as the logic test does this for you:

Code: Select all

'*** Input Year in box at top of the screen
INPUT Y


'*** Perform MOD functions on year divided by 4, 100, and 400
L=Y%4
C100=Y%100
C400=Y%400


'*** Logic test to see if year is a Century, Normal, or not a Leap Year
IF L=0 AND (C100=0 AND C400=0) THEN
   PRINT "Year "&Y&" is a Century Leap Year"
   GOTO endPROG
ELSE
   PRINT "Year "&Y&" is not a Century Leap Year" 
   IF L=0 AND (C100<>0 AND C400<>0) THEN
      PRINT "Year "&Y&" is a normal Leap Year"
   ELSE
      PRINT "Year "&Y&" is not a Leap Year"
   ENDIF
ENDIF

endPROG:
   STOP
This takes care of your every four years, your every 100 years (century years), and also determines if a century is really a leap year (by dividing by 100 and 400).

George


Joel wrote:
Mon Oct 02, 2017 8:18 pm
Hi there,
For date calculations I needed a program to calculate the number of days since 1/1/1600. This program can also be used to calculate the difference between two dates, for example.

Code: Select all

INPUT year, month,day
PRINT days_1600(year,month,day) 'calculates the number of days since 1600/1/1

'c'

DEF days_1600(year,month,day)
'set leapyear (is this year a leapyear? and count leap years since 1600
leaps=leaps2(year)
IF year=1600 THEN 
 leapyear=1 
ELSE 
 IF leaps2(year-1)=leaps THEN 
  leapyear=0 
 ELSE 
  leapyear=1
 ENDIF
ENDIF

dyear=year-1600
IF NOT num_in_range(month,1,12) THEN RETURN -1'valid input?
IF NOT num_in_range(day,1,31) THEN RETURN -1 'upper limit will be checked later
RESTORE
result=0
 FOR days_in_month=1 TO month-1
  READ days
  result=result+days 'sum up all days of prev month
 NEXT days_in_month
 result=result+day 'add the input day
 READ days 'for validity purpose
 IF month=2 AND leapyear THEN days+=1 'days will not longer be used so this is for next line
 IF days<day THEN RETURN-1 'invalid date
 result=result+dyear*365+leaps 'add days of prev years and number of leap years
 IF month<=2 AND leapyear THEN result-=1 'in jan or feb ignore the this year leap status 
 RETURN result
 DATA 31,28,31,30,31,30,31,31,30,31,30,31
END DEF

DEF num_in_range(num, num1,num2)
 IF num<num1 OR num>num2 THEN RETURN 0 ELSE RETURN 1
END DEF

DEF leaps2(year)
 dyear=year-1600
 each4=FLOOR(dyear/4)
 each100=FLOOR(dyear/100)
 each400=FLOOR(dyear/400)
 result=each4-each100+each400+1'1600 is a leap year itself
 RETURN result
END DEF
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)

Joel
Posts: 57
Joined: Fri Jan 15, 2016 1:36 pm
My devices: miniipad
Flag: Germany

Re: counting the days since 1600/1/1

Post by Joel »

Hello, George,
Thank you for your suggestions.
I understand your approach. You use the MOD function to check if your year is a leap year or not. With this problem you can use the MOD function very usefully.

The problem for me, however, is to calculate the sum of all leap years between 1600 and my year number. Finally, I would like to count the number of days since 1600, which is best done by multiplying 365 with "normal whole years" and taking into account the number of leap years in between as well as the rest of the year of my year number.

Thus I calculate the number of leap years in between with the integer division:

B1: dyear=year-1600
B2: each4=FLOOR (dyear/4)
B3: each100=FLOOR (dyear/100)
B4: each400=FLOOR (dyear/400)
B5: result=each4-each100+each400+1' Number of all leap years between 1600 and year)

For grammatical reasons, every4... every100... would probably be more correct instead of each4... each100... each100; -)

Best regards, Joel

User avatar
GeorgeMcGinn
Posts: 435
Joined: Sat Sep 10, 2016 6:37 am
My devices: IPad Pro 10.5in
IMac
Linux i386
Windows 7 & 10
Location: Venice, FL
Flag: United States of America
Contact:

Re: counting the days since 1600/1/1

Post by GeorgeMcGinn »

Why are you using FLOOR? These functions have specific rules about rounding up or down or not rounding, and if accuracy is what you are looking for, you need to use MOD.

In working with GPS data, sometimes the wind direction may come in greater than 360 degrees. On some devices, you will get 405, which you will need to use MOD to get the remainder, the true degree reading.

The problem is that if you don't use MOD, FLOOR may round up or not round up and you will miss days.

For days calculation, your better to loop through the years, and follow my formula add 365 or 366 as prescribed.

Same when counting days in February, check the date using MOD and you will never miss or add days.

And the problem gets larger when you count days over hundreds or years.

Joel wrote:
Sat Oct 07, 2017 3:14 pm
Hello, George,
Thank you for your suggestions.
I understand your approach. You use the MOD function to check if your year is a leap year or not. With this problem you can use the MOD function very usefully.

The problem for me, however, is to calculate the sum of all leap years between 1600 and my year number. Finally, I would like to count the number of days since 1600, which is best done by multiplying 365 with "normal whole years" and taking into account the number of leap years in between as well as the rest of the year of my year number.

Thus I calculate the number of leap years in between with the integer division:

B1: dyear=year-1600
B2: each4=FLOOR (dyear/4)
B3: each100=FLOOR (dyear/100)
B4: each400=FLOOR (dyear/400)
B5: result=each4-each100+each400+1' Number of all leap years between 1600 and year)

For grammatical reasons, every4... every100... would probably be more correct instead of each4... each100... each100; -)

Best regards, Joel
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)

Post Reply