Julian date code for picaxe

tikeda

Member
Here is a program for calculating Julian day numbers with a base date of 01-Jan-2000 (= day zero). With word variables, the calculations shouldn't overflow until after 31-Dec-2178. I have tried to minimize the number of time-eating multiplication and division steps in this code. Also, with X1/X2 Picaxe versions, shift-right binary math is available.

Formulas are derived from the following sources:
Eric W. Weisstein
Tracy Allen

Code:
'Julian day number (JDN) calculator
'Created: 2007-12-23 (T.Ikeda - KA1OS)
'Latest mod: 2008-01-27

'Works with dates from 2000-01-01 to 2178-12-31
'
'On 2000-01-01, JDN = 0 (Epoch: 2000-01-01) and increments
'from there. This program properly accounts for 2100
'not being a leap year.
'
'In the simulator, this doesn't over overflow until
'2178-06-05 (05-Jun-2179). In theory, the processor should
'overflow in one of the calculation steps (367 * YYY) when
'the YYY is 179
'
'Formulas derived from the following sources and optimized
'for Picaxe math (minimizing multiplication & division
'steps in the calculations):
'	http://scienceworld.wolfram.com/astronomy/JulianDate.html
'		by Eric W. Weisstein
'	http://www.emesystems.com/BS2math4.htm
'		by Tracy Allen
'
'Note that this program uses *no* error checking for illegal
'	dates: e.g. 2007-13-32
'

Symbol JDN = w4
Symbol YYY = b5	'0 to 178, corresponding to years 2000-2178
Symbol MM = b6	'Months: 1-12
Symbol DD = b7	'Day: 1-31

'Plug-in values for testing... Remove after debugging.
'06-Jun-2010 =
YYY = 10
MM = 6
DD = 6

JDN = 0
If MM > 2 Then
	JDN = 1
End If

JDN = YYY + JDN * 7 / 4
JDN = 367 * YYY - JDN
JDN = MM * 3912 / 128 + DD - 31 + JDN

'*******************************************
'X1/X2 parts can use shift right instead of divides.
'JDN = (YYY + JDN) * 7 >> 2
'JDN = (367 * YYY) - JDN
'JDN = ((MM * 3912) >> 7) + DD - 31 + JDN
'*******************************************

'Add correction for 2100 not being a leap year...
If JDN > 36584 Then
	JDN = JDN -1
End If

'Testing output... Remove after debugging.
bintoascii JDN, b0, b1, b2, b3, b4
sertxd (b0,b1,b2,b3,b4)

End
 

andyshrimpton

New Member
Julian date problem

Hi Ikeda

Thanks for your code.

I am trying to understand what is going on badly.

I am trying in my code to see how many days are between to dates. for example 1/1/2010 and 1/1/2012

I have found loads on google but alway end up with a much larger number with 7 figures of which the picaxe can not handle

How does your code work, what am i missing here, i am sure it very simple

Regards


Andy
 

andyshrimpton

New Member
Understand code

Glad to say i understand the code i was entering the day as the month so it was not working.

Why is the code limited to the year 2178?

Thanks for this code i think it going to help me

Andy
 

westaust55

Moderator
It is limited to 2178 because the max value in a word variable is 65535.

The number of days from 1 Jan 2000 to 31 Dec 2178 is getting close to that maximum value.
 

westaust55

Moderator
Yes it (2100) is.

A leap year occurs when:
the year is evenly divisible by four,
but not a leap year if it is also evenly divisible by 100 unless also divisible by 400.​


Somehow think I will not be around in 2100 to personal check the fact (just in case the calendar is re-worked) though.
But having the code correct is good for posterity.
 

hippy

Technical Support
Staff member
@ Westaust55 : Don't the rules show that 2100 is not a leap year ?

Divisible by 4 ... yes, so leap year so far, and
Divisible by 100 ... yes, so non leap year so far, and
Divisible by 400 ... no, so remains a non leap year
 

DOwenWilliams

New Member
leap year XOR

The rule for deciding whether a year is a leap year is very simple if we use the eXclusive-OR (XOR) operator. In BASIC:

IF (Y MOD 4 = 0) XOR (Y MOD 100 = 0) XOR (Y MOD 400 = 0) THEN ' Y is a leap year.

In most dialects of BASIC (I'm not sure about Picaxe) the brackets can be omitted.

Curiously, the three divisors (4, 100, 400) are all equivalent, and can be put into the formula in any order.

Of course, for example, (Y MOD 4 = 0) is true if and only if Y is exactly divisible by 4.

David
 

Hansen

Member
After looking at the code for my project where i need Julian Date at 7 char format
output from the DS1307

The new change will only work to around 2030, ( at that time I think we got very strong PACAXE chip )

some place in the code i put in code linie for test

Code:
#PICAXE 18x
'Julian day number (JDN) calculator
'Created: 2007-12-23 (T.Ikeda - KA1OS)
'Latest mod: 2008-01-27

'Latest mod: 31/1-2012 
'Change output to true JD format
'with the change i will work to about year 2030

'Works with dates from 2000-01-01 to 2178-12-31
'
'On 2000-01-01, JDN = 0 (Epoch: 2000-01-01) and increments
'from there. This program properly accounts for 2100
'not being a leap year.
'
'In the simulator, this doesn't over overflow until
'2178-06-05 (05-Jun-2179). In theory, the processor should
'overflow in one of the calculation steps (367 * YYY) when
'the YYY is 179
'
'Formulas derived from the following sources and optimized
'for Picaxe math (minimizing multiplication & division
'steps in the calculations):
'	http://scienceworld.wolfram.com/astronomy/JulianDate.html
'		by Eric W. Weisstein
'	http://www.emesystems.com/BS2math4.htm
'		by Tracy Allen
'
'Note that this program uses *no* error checking for illegal
'	dates: e.g. 2007-13-32
'
pause 8000 ' Just for delay to open terminal window

Symbol JDN = w4
Symbol YYY = b5	'0 to 178, corresponding to years 2000-2178
Symbol MM = b6	'Months: 1-12
Symbol DD = b7	'Day: 1-31

'06-Jun-2010 = 03809 + 2451545 = 2455354 = Corent 2455354

'1 jan 2035 = 2464329


'Read date from DS1307 
i2cslave %11010000, i2cslow, i2cbyte
'test setup DS1307
'Writei2c 0,($00, $59, $11, $07, $31, $01, $12, $10) 
'pause 20
readi2c 4,(b0, b1, b2)

'test data without ds1307 read
'YYY = 12
'MM = 1
'DD = 31

'output from DS1307 convert to useble for JD calc
'6 next line use if PICAXE chip not 20x2, 28x1,28x2,40x1, 40x2
DD = b0/16*10 ; get tens part
DD = b0 //16 + DD ; then add units part 
MM = b1/16*10 ; get tens part
MM = b1 //16 + MM ; then add units part 
YYY = b2/16*10 ; get tens part
YYY = b2 //16 + YYY ; then add units part 

'output from DS1307 convert to useble for JD calc
'3 next line use if PICAXE chip IS 20x2, 28x1,28x2,40x1, 40x2

'DD = BCDTOBIN b0
'MM = BCDTOBIN b1
'YYY = BCDTOBIN b2

JDN = 0
If MM > 2 Then
	JDN = 1
End If

JDN = YYY + JDN * 7 / 4
JDN = 367 * YYY - JDN
JDN = MM * 3912 / 128 + DD - 31 + JDN

'*******************************************
'X1/X2 parts can use shift right instead of divides.
'JDN = (YYY + JDN) * 7 >> 2
'JDN = (367 * YYY) - JDN
'JDN = ((MM * 3912) >> 7) + DD - 31 + JDN
'*******************************************

'Add correction for 2100 not being a leap year...
If JDN > 36584 Then
	JDN = JDN -1
End If

'Testing output... Remove after debugging.


JDN = JDN + 51545 ' add 5 last digit on the base 1 jan 2000 JD
bintoascii JDN, b0, b1, b2, b3, b4

sertxd ("31/1-2012 = JD 24")
sertxd (b0,b1,b2,b3,b4)

End

' output 31 jan 2012 = 31/1-2012 = JD 2455958
 
Top