imageblitzbasic

Author Topic: Time to Days, hours, minutes and seconds  (Read 880 times)

Offline MrTAToad

  • HelpEditors
  • Prof. Inline
  • ****
  • Posts: 5341
  • Its me!
    • View Profile
    • Un-Map.com
Re: Time to Days, hours, minutes and seconds
« Reply #15 on: 2012-May-24 »
Quote
Will see what output I get on my home machine this weekend as that has Delphi installed as well as Free Pascal on Linux & will enter the same dates you tried.
That'll be good - if they differ, then there is a mathematical problem somewhere.  Its possible that some extra leap years were being taken into account too...

I've produced this, which uses a different calculation for things, and is based on this site http://www.onlineconversion.com/julian_date.htm

Download : http://dl.dropbox.com/u/25216439/Test2.app.rar

Offline Kitty Hello

  • code monkey
  • Administrator
  • Prof. Inline
  • *****
  • Posts: 10277
  • here on my island the sea says 'hello'
    • View Profile
    • http://www.glbasic.com
Re: Time to Days, hours, minutes and seconds
« Reply #16 on: 2012-May-24 »
Wow, that's very handy. Now I only need a few days off to make some notes on this. ;)

Online fuzzy70

  • Prof. Inline
  • *****
  • Posts: 555
  • Look left, Look right, LOOK OUT!!
    • View Profile
Re: Time to Days, hours, minutes and seconds
« Reply #17 on: 2012-May-24 »
I have found out why the code gave incorrect results on pre 1585 dates, just a pure simple typo.

The original code in the Pascal version of the MJD function was

THEN B:=-2+TRUNC((YEAR+4716)/4)-1179


The converted was

b=2+INTEGER((year%+4716)/4)-1179

I have underlined & made bold the difference, Just a simple "-" sign was missing & a very easy mistake to make thanks to := being used in Pascal. Here is the amended version & I have tested it on the dates you had problems with & they return the correct values back

Code: [Select]
LOCAL day%,month%,year%,hour%

DEBUG MJD(24,5,1500,12)+"\n"
CALDAT(-130923.5,day%,month%,year%,hour%)
DEBUG day%+" "+month%+" "+year%+" "+hour%

FUNCTION MJD:day%,month%,year%,hour
LOCAL a,b%

a=10000.0*year%+100.0*month%+day%
IF month%<=2
INC month%,12
DEC year%
ENDIF

IF a<=15821004.1
b=-2+INTEGER((year%+4716)/4)-1179
ELSE
b=INTEGER(year%/400)-INTEGER(year%/100)+INTEGER(year%/4)
ENDIF

a=365.0*year%-679004.0
RETURN a+b+INTEGER(30.6001*(month%+1))+day%+hour/24.0
ENDFUNCTION

FUNCTION CALDAT%:value,BYREF day%,BYREF month%,BYREF year%,BYREF hour%
LOCAL b%,d%,f%
LOCAL jd,jd0,c,e

jd=value+2400000.5
jd0=INTEGER(jd+0.5)
IF jd0<2299161.0
c=jd0+1524.0
ELSE
b%=INTEGER((jd0-1867216.25)/36524.25)
c=jd0+(b-INTEGER(b%/4))+1525.0
ENDIF

d%=INTEGER((c-122.1)/365.25); e=365.0*d+INTEGER(d%/4)
f%=INTEGER((c-e)/30.6001)
day%=INTEGER(c-e+0.5)-INTEGER(30.6001*f%); month%=f%-1-12*INTEGER(f%/14)
year%=d%-4715-INTEGER((7+month%)/10); hour%=24.0*(jd+0.5-jd0)
ENDFUNCTION

Lee
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

Offline MrTAToad

  • HelpEditors
  • Prof. Inline
  • ****
  • Posts: 5341
  • Its me!
    • View Profile
    • Un-Map.com
Re: Time to Days, hours, minutes and seconds
« Reply #18 on: 2012-May-24 »
Ah yes - mis-read that :)

Offline MrTAToad

  • HelpEditors
  • Prof. Inline
  • ****
  • Posts: 5341
  • Its me!
    • View Profile
    • Un-Map.com
Re: Time to Days, hours, minutes and seconds
« Reply #19 on: 2012-May-24 »
I'm incorporating both versions into the program now :)

Your version does seem to be an out by hour though :

Code: [Select]
DEBUG MJD(24,5,2012,17)+"\n"
CALDAT(56071.70833,day%,month%,year%,hour%)
DEBUG day%+" "+month%+" "+year%+" "+hour%
END

Gives :

56071.70833
24 5 2012 16
« Last Edit: 2012-May-24 by MrTAToad »

Online fuzzy70

  • Prof. Inline
  • *****
  • Posts: 555
  • Look left, Look right, LOOK OUT!!
    • View Profile
Re: Time to Days, hours, minutes and seconds
« Reply #20 on: 2012-May-24 »
Interesting, seems to happen on any hour >=14 regardless of year etc. Time for some investigation me thinks ;)

Lee

Sent from my GT-I5700 using Tapatalk 2
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

Offline MrTAToad

  • HelpEditors
  • Prof. Inline
  • ****
  • Posts: 5341
  • Its me!
    • View Profile
    • Un-Map.com
Re: Time to Days, hours, minutes and seconds
« Reply #21 on: 2012-May-24 »
I've got a nasty feeling its a rounding problem.

For example, hour ends up being 16.992, which would mean when converted to an integer would come out at as 16...

This code modification seems to work out okay though :

Code: [Select]
hour%=(24.0*(jd+0.5-jd0))+0.05
« Last Edit: 2012-May-24 by MrTAToad »

Online fuzzy70

  • Prof. Inline
  • *****
  • Posts: 555
  • Look left, Look right, LOOK OUT!!
    • View Profile
Re: Time to Days, hours, minutes and seconds
« Reply #22 on: 2012-May-24 »
It is indeed a rounding problem. Using the one prior to your 0.05 I done it by hand & the 17 hour / 24 is 0.7083333333 recurring. Adding the extra 3's returned the correct answer.

Lee

Sent from my GT-I5700 using Tapatalk 2
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

Offline Ian Price

  • Global Moderator
  • Prof. Inline
  • ****
  • Posts: 3099
  • On the shoulders of giants.
    • View Profile
    • My Apps
Re: Time to Days, hours, minutes and seconds
« Reply #23 on: 2012-May-24 »
You lot obviously have too much time on your hands... ;) :P
I came. I saw. I played.

Offline erico

  • Prof. Inline
  • *****
  • Posts: 1936
    • View Profile
    • Portfolio
Re: Time to Days, hours, minutes and seconds
« Reply #24 on: 2012-May-24 »
Ok, so when do we test the code on the Delorian? :P

Offline Slydog

  • Prof. Inline
  • *****
  • Posts: 800
  • KodeSource
    • View Profile
    • KodeSource
Re: Time to Days, hours, minutes and seconds
« Reply #25 on: 2012-May-24 »
Ok, so when do we test the code on the Delorian? :P

When we can get our FPS up to 88!
- Do pessimistic cats have 9 deaths?

Offline MrTAToad

  • HelpEditors
  • Prof. Inline
  • ****
  • Posts: 5341
  • Its me!
    • View Profile
    • Un-Map.com
Re: Time to Days, hours, minutes and seconds
« Reply #26 on: 2012-May-24 »
I've finished my conversion program.  It generally works well, but does occasionally suffer from occasional rounding errors.  Usually it's only out by a second, but occasionally I have seen it out by a day.

Download : http://dl.dropbox.com/u/25216439/DateToJulian.app.rar

Offline erico

  • Prof. Inline
  • *****
  • Posts: 1936
    • View Profile
    • Portfolio
Re: Time to Days, hours, minutes and seconds
« Reply #27 on: 2012-May-24 »
 :D :good:

Offline MrTAToad

  • HelpEditors
  • Prof. Inline
  • ****
  • Posts: 5341
  • Its me!
    • View Profile
    • Un-Map.com
Re: Time to Days, hours, minutes and seconds
« Reply #28 on: 2012-May-24 »
Heh  :good:

Here is the code for the program :

Code: [Select]
GLOBAL gDDguiMinControlDimension%=16

LOCAL day%,month%,year%,hour%
LOCAL sW%=320,sH%=240
LOCAL size%,temp$,v
LOCAL dateTime$[],date$[],time$[]

size%=(sW%/6)-8

DIM dateTime$[0]
IF SPLITSTR(PLATFORMINFO$("TIME"),dateTime$[]," ")>=2
// Get the date
DIM date$[0]
DIM time$[0]

IF SPLITSTR(dateTime$[0],date$[],"-")<>3 OR SPLITSTR(dateTime$[1],time$[],":")<>3
DDgui_msg("Date/Time split is invalid",FALSE,"* Error *")
RETURN FALSE
ENDIF
ELSE
DDgui_msg("Can't get current date and time",FALSE,"* Error *")
RETURN FALSE
ENDIF

LOADFONT "Media/smalfont.png",0
SETFONT 0

DDgui_pushdialog(0,0,sW%,sH%)
DDgui_tab("tab","Julian To Value,f1,type1,wday1,day1,wmonth1,month1,wyear1,year1,whour1,hour1,wmin1,min1,wsec1,sec1,convert1,wresult|"+ _
"Value To Julian,f2,value,type2,convert2,wday2,day2,wmonth2,month2,wyear2,year2,whour2,hour2,wmin2,min2,wsec2,sec2")
DDgui_framestart("f1","Enter Julian Date",sW%-8)
DDgui_checkbox("usnavy1"," Use US Navy Routine",sW%-8,0)
DDgui_radio("type1","AD|BC",sW%-8);
DDgui_widget("wday1","Day",size%,0); DDgui_numbertext("day1",date$[2],size%)
DDgui_widget("wmonth1"," Mnth",size%,0); DDgui_numbertext("month1",date$[1],size%)
DDgui_widget("wyear1"," Year",size%,0); DDgui_numbertext("year1",date$[0],size%)
DDgui_widget("whour1"," Hour",size%,0); DDgui_numbertext("hour1",time$[0],size%)
DDgui_widget("wmin1"," Min",size%,0); DDgui_numbertext("min1",time$[1],size%)
DDgui_widget("wsec1"," Sec",size%,0); DDgui_numbertext("sec1",time$[2],size%)
DDgui_button("convert1","Convert To Modified Julian Date value",sW%-18,0)
DDgui_widget("wresult","Resulting date value :",0,0); DDgui_numbertext("result1","",128); DDgui_set("result1","READONLY",TRUE)
DDgui_frameend()

DDgui_framestart("f2","Enter Modified Julian Date value",sW%-8)
DDgui_numbertext("value","",sW%-18)
DDgui_checkbox("usnavy2"," Use US Navy Routine",sW%-8,0)
DDgui_button("convert2","Convert To Standard calendar Format",sW%-18,0)
DDgui_radio("type2","AD|BC",sW%-8); //DDgui_set("type2","READONLY",TRUE)
DDgui_widget("wday2","Day",size%,0); DDgui_numbertext("day2","",size%); DDgui_set("day2","READONLY",TRUE)
DDgui_widget("wmonth2"," Mnth",size%,0); DDgui_numbertext("month2","",size%); DDgui_set("month2","READONLY",TRUE)
DDgui_widget("wyear2"," Year",size%,0); DDgui_numbertext("year2","",size%); DDgui_set("year2","READONLY",TRUE)
DDgui_widget("whour2"," Hour",size%,0); DDgui_numbertext("hour2","",size%); DDgui_set("hour2","READONLY",TRUE)
DDgui_widget("wmin2"," Min",size%,0); DDgui_numbertext("min2","",size%); DDgui_set("min2","READONLY",TRUE)
DDgui_widget("wsec2"," Sec",size%,0); DDgui_numbertext("sec2","",size%); DDgui_set("sec2","READONLY",TRUE)
DDgui_frameend()

WHILE TRUE
DDgui_show(FALSE)
SHOWSCREEN

IF DDgui_get("usnavy1","CLICKED")
IF INTEGER(DDgui_get("usnavy1","SELECT"))
// US Navy needs access to AD/BC and mins and secs
DDgui_set("type1","READONLY",FALSE)
DDgui_set("min1","READONLY",FALSE)
DDgui_set("sec1","READONLY",FALSE)
ELSE
// Fuzzy 70 doesn't use AC/BC or mins or secs
DDgui_set("type1","READONLY",TRUE)
DDgui_set("min1","READONLY",TRUE)
DDgui_set("sec1","READONLY",TRUE)
DEBUG "Here2\n"
ENDIF
ELSEIF DDgui_get("convert1","CLICKED")
LOCAL day%,month%,year%,hour%,mins%,sec%,isBC%

year%=INTEGER(DDgui_get("year1","TEXT"))
IF year%=0
DDgui_msg("There is no year 0 !",FALSE,"* Error *")
ELSE
day%=INTEGER(DDgui_get("day1","TEXT"))
month%=INTEGER(DDgui_get("month1","TEXT"))
hour%=INTEGER(DDgui_get("hour1","TEXT"))
mins%=INTEGER(DDgui_get("min1","TEXT"))
sec%=INTEGER(DDgui_get("sec1","TEXT"))

IF INTEGER(DDgui_get("usnavy1","SELECT"))
IF INTEGER(DDgui_get("type1","SELECT"))=0
isBC%=FALSE
IF year%=1582 AND month%=10 AND (day%>4 AND day%<15)
DDgui_msg("Error 5/10/1582 to 14/10/1582",FALSE,"* Error *")
CONTINUE
ENDIF
ELSE
isBC%=TRUE
ENDIF

DDgui_set("result1","TEXT",cal_to_jd$(isBC%,year%,month%,day%,hour%,mins%,sec%))
ELSE
IF year%=1582 AND month%=10 AND (day%>4 AND day%<15)
DDgui_msg("Error 5/10/1582 to 14/10/1582",FALSE,"* Error *")
ELSE
DDgui_set("result1","TEXT",MJD(day%,month%,year%,hour%))
ENDIF
ENDIF
ENDIF
ELSEIF DDgui_get("convert2","CLICKED")
LOCAL value$,day%,month%,year%,hour%,mins%,sec%,result%

value$=DDgui_get$("value","TEXT")
IF value$=""
DDgui_msg("No date value entered",FALSE,"* Error *")
ELSE
IF INTEGER(DDgui_get("usnavy2","SELECT"))
result%=jd_to_cal(value$,day%,month%,year%,hour%,mins%,sec%)
IF result%=TRUE
DDgui_set("type2","SELECT",1)
ELSE
DDgui_set("type2","SELECT",0)
ENDIF

DDgui_set("min2","TEXT",RIGHT$("00"+mins%,2))
DDgui_set("sec2","TEXT",RIGHT$("00"+sec%,2))
ELSE
IF CALDAT(value$,day%,month%,year%,hour%)=TRUE
DDgui_set("type2","SELECT",0)
ELSE
DDgui_set("type2","SELECT",1)
ENDIF

DDgui_set("min2","TEXT","N/A")
DDgui_set("sec2","TEXT","N/A")
ENDIF

DDgui_set("day2","TEXT",RIGHT$("00"+day%,2))
DDgui_set("month2","TEXT",RIGHT$("00"+month%,2))
DDgui_set("year2","TEXT",year%)
DDgui_set("hour2","TEXT",RIGHT$("00"+hour%,2))
ENDIF
ENDIF
WEND

FUNCTION MJD:day%,month%,year%,hour
LOCAL a,b%

a=10000.0*year%+100.0*month%+day%
IF month%<=2
INC month%,12
DEC year%
ENDIF

IF a<=15821004.1
b%=-2+INTEGER((year%+4716)/4)-1179
ELSE
b%=INTEGER(year%/400)-INTEGER(year%/100)+INTEGER(year%/4)
ENDIF

a=365.0*year%-679004.0
RETURN a+b%+INTEGER(30.6001*(month%+1))+day%+hour/24.0
ENDFUNCTION

FUNCTION CALDAT%:value,BYREF day%,BYREF month%,BYREF year%,BYREF hour%
LOCAL b%,d%,f%
LOCAL jd,jd0,c,e,r%

jd=value+2400000.5
jd0=INTEGER(jd+0.5)
IF jd0<2299161.0
c=jd0+1524.0
ELSE
b%=INTEGER((jd0-1867216.25)/36524.25)
c=jd0+(b-INTEGER(b%/4))+1525.0
ENDIF

d%=INTEGER((c-122.1)/365.25); e=365.0*d%+INTEGER(d%/4)
f%=INTEGER((c-e)/30.6001)
day%=INTEGER(c-e+0.5)-INTEGER(30.6001*f%); month%=f%-1-12*INTEGER(f%/14)
year%=d%-4715-INTEGER((7+month%)/10); hour%=INTEGER((24.0*(jd+0.5-jd0))+0.005)

IF year%<0
year%=-year%
r%=FALSE
ELSE
r%=TRUE
ENDIF

RETURN r%
ENDFUNCTION

INLINE
extern "C" double floor (      double x );
ENDINLINE

FUNCTION cal_to_jd$:isBC%, y%, m%, d%, h%, mn%, s%
INLINE
long jy,ja,jm,gregcal=15 + 31*( 10 + 12*1582);
double dayfrac,frac,jd0,jd,intgr;

if (isBC)
{
    y = -y + 1;
    }

if (m > 2)
{
jy = y;
jm = m + 1;
}
else
{
jy = y - 1;
jm = m + 13;
}

intgr=floor((365.25*jy)+(30.6001*jm)+d+1720995);

//check for switch to Gregorian calendar
if (d + 31*(m + 12*y) >= gregcal)
{
ja = floor(0.01*jy);
intgr+=2 - ja + floor(0.25*ja);
}

//correct for half-day offset
dayfrac = h/24.0 - 0.5;
if (dayfrac < 0.0)
{
dayfrac++;
intgr--;
}

//now set the fraction of a day
frac = dayfrac + (mn + s/60.0)/60.0/24.0;
    //round to nearest second
    jd0 = (intgr + frac)*100000.0;
    DEBUG("Here : "); DEBUG(DGInt(jd0)); DEBUG("\n");

    jd  = floor(jd0);
    if (jd0 - jd > 0.5) jd++;
    return FORMAT_Str(16,6,jd/100000.0);
ENDINLINE
ENDFUNCTION

FUNCTION jd_to_cal%:jd,BYREF day%,BYREF month%,BYREF year%,BYREF hour%,BYREF mins%,BYREF secs%
INLINE
bool isBC;
long j1,j2,j3,j4,j5;
double frac,dayfrac,f;
long gregjd = 2299161;
long intgr;

intgr=floor(jd);
frac=jd-intgr;
if (intgr>=gregjd)
{
double tmp;

tmp=floor( ( (intgr - 1867216) - 0.25 ) / 36524.25 );
j1=intgr + 1 + tmp - floor(0.25*tmp);
}
else
{
j1=intgr;
}

dayfrac=frac+0.5;

if (dayfrac>=1.0)
{
dayfrac--;
j1++;
}

j2=j1+1524;
j3=floor(6680.0 + ( (j2 - 2439870) - 122.1 )/365.25);
j4=floor(j3*365.25);
j5=floor( (j2 - j4)/30.6001 );

day=floor(j2 - j4 - floor(j5*30.6001));
month=floor(j5-1);
if (month>12) month-=12;
year=floor(j3-4715);
if (month>2) year--;
if (year<=0) year--;


// get time of day from day fraction
hour=floor(dayfrac * 24.0);
mins=floor((dayfrac*24.0 - hour)*60.0);
f=((dayfrac*24.0 - hour)*60.0 - mins)*60.0;
secs=floor(f);
if (f>0.5) secs++;

if (year<0)
{
isBC=true;
year=-year;
}
else
{
isBC=false;
}

return isBC;
ENDINLINE
ENDFUNCTION

Online fuzzy70

  • Prof. Inline
  • *****
  • Posts: 555
  • Look left, Look right, LOOK OUT!!
    • View Profile
Re: Re: Time to Days, hours, minutes and seconds
« Reply #29 on: 2012-May-24 »
You lot obviously have too much time on your hands... ;) :P

I was lucky in that I already wrote the code years ago so all the brain ache of the maths is long behind me lol.

Still have another 100 odd Pascal source files that make up the whole program which the ones I posted are the little baby ones ;)

The whole lot basically works out planetary positions, eclipses, new moons, comet paths etc which I used to control my old telescope.

examples of what can be done with a cheap webcam & sub    £100 telescope.

Lee

Sent from my GT-I5700 using Tapatalk 2
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)