Yahoo Answers is shutting down on May 4th, 2021 (Eastern Time) and beginning April 20th, 2021 (Eastern Time) the Yahoo Answers website will be in read-only mode. There will be no changes to other Yahoo properties or services, or your Yahoo account. You can find more information about the Yahoo Answers shutdown and how to download your data on this help page.

Jim
Lv 7
Jim asked in Science & MathematicsMathematics · 9 years ago

math: gregorian date to day number?

not acceptable: julian day number calculations.

rules are provided here:http://www.sizes.com/time/cal_gregorian.htm

you can code in javascript, c, or autoit, or maybe pseudocode.

this is not for a college project. I am stumped trying to produce appropriate math to convert gregorian day number to date and back.

I have this:

func GregorianToDtime($Y,$Mo,$D,$H,$Mi,$S,$ms, byref $dtime) ;do we have to offset these by 1?

;-----function good to 100,000 years if I coded it right.

;-----we will allow for a zero year.

;-----given gregorian date, convert to gregorian day number, then to dtime.

local $days= mod($Y,4)*365*$Y ;Every year whose number is not divisible by 4 without remainder, consists of 365 days;

;$days+=ceil((mod($Y,4) * mod($Y,100)>0)) * 366 * $Y ;this doesn't end up 1 when any mods are zeros! ;every year which is so divisible, but is not divisible by 100, of 366;

;$days+=((mod($Y,4) * mod($Y,100)>0)?1:0) * 366 * $Y ;this doesn't end up 1 when any mods are zeros! ;every year which is so divisible, but is not divisible by 100, of 366;

;this language doesn't have a ternary operator,so we implement as an if statement

local $temp=0

if (mod($Y,4) * mod($Y,100)>0) then ;this doesn't end up 1 when any mods are zeros!

$temp=1

endif

$days += $temp * 366 * $Y ;every year which is so divisible, but is not divisible by 100, of 366;

$days += (int($Y/100) - int($Y/400)) * 366; every year divisible by 100 but not by 400, again of 366.

$days += int($Y/4000) * 365 ;years divisible by 4000 should consist of 365 days.

$days += NumDaysInMonth( $Y,$Mo)

$days += $D

$days -= 1 ;subtract 1 day so days start at 0

$dtime = ($days * 1000*60*60*24) + ($H*1000*60*60) + ($Mi*60*1000) + ($S*1000) + $ms

return $dtime

endfunc

;http://www.sizes.com/time/cal_gregorian.htm

func DtimeToGregorian($dtime,byref $Y,byref $Mo,byref $D,byref $H,byref $Mi,byref $S,byref $ms) ;do we have to offset these by 1?

;-----function good to 100,000 years if I coded it right.

$ms=Mod($dtime,1000)

$S=Mod(Int($dtime / 1000),60)

$Mi=Mod(Int($dtime / (1000*60)),60)

$H=Mod(Int($dtime / (1000*60*60)),24)

local $days = int($dtime / (1000*60*60*24))

$days+=1 ;required for conversion due to offset of 1 day in gregorian calendar system

;-----determine the year, it's the biggest number

local $year=0, $year365=int($days/365), $year366=int($days/366)

if (mod($year366,100) * mod($year366,400) > 0 or mod($year365,4) * mod($year366,100) > 0) then

$Y = int($days/366)

$days -= ($Y*366)

elseif (mod($year365,4) > 0 or mod($year365, 4000)>0) then

$Y = int($days/365)

$days -= ($Y*365)

endif

local $i,$monthdays

for $Mo=12 to 1 step -1

$monthdays = SumOfDaysUpTo1stDayOfMonthWithoutYear( $Y,$Mo)

if ($monthdays < $days) then

;-----match!

$days-=NumDaysInMonth($Y,$Mo)

$D=$days

exitloop

endif

next

;-----return an array structure containing the resulting DTime

local $a[8]

$a[0]=7

$a[1]=$Y

$a[2]=$Mo

$a[3]=$D

$a[4]=$H

$a[5]=$Mi

$a[6]=$S

$a[7]=$ms

return $a

endfunc

func LeapIndex($Y)

if (0<>mod($Y, 4)) then

return 0;

elseif (0<>mod($Y, 100)) then

return 1;

elseif (0<>mod($Y, 400)) then

return 0;

else

return 1;

endif

endfunc

func NumDaysInMonth($Y,$Mo)

switch $mo

case 1,8,12

return 31

case 2

return LeapIndex($Y) + 28

case 3,5,7,10

return 31

case 4,6,9,11

return 30

endswitch

endfunc

func SumOfDaysUpTo1stDayOfMonthWithoutYear( $Y,$Mo)

;this is the sum of days up to 1st day of $Mo

local $sum=0,$i

for $i = 1 to $Mo-1

$sum += NumDaysInMonth($Y,$Mo)

next

return $sum+1

endfunc

1 Answer

Relevance
  • 9 years ago
    Favorite Answer

    I code in IDL and have this if of any use.

    IDL very similar to FORTRAN 90 or PASCAL and as higher level language to the one you appear to be using you should be able to follow it and invert it for your problem or at least make it iterative. There are many other date routines in the IDL library.

Still have questions? Get your answers by asking now.