How to convert FORTRAN subroutine to awk function?

Hi All I am trying to convert some Fortran subroutine to awk function , those who know kindly explain how to define function in awk, and how to call function

Fortran subroutine looks somewhat like this

  SUBROUTINE GDATE (JD, YEAR,MONTH,DAY)
C
C---COMPUTES THE GREGORIAN CALENDAR DATE (YEAR,MONTH,DAY)
C   GIVEN THE JULIAN DATE (JD).
C

     INTEGER JD,YEAR,MONTH,DAY,I,J,K
C
    L= JD+68569
    N= 4*L/146097
    L= L-(146097*N+3)/4
    I= 4000*(L+1)/1461001
    L= L-1461*I/4+31
    J= 80*L/2447
    K= L-2447*J/80
    L= J/11
    J= J+2-12*L
    I= 100*(N-49)+I+L
C
    YEAR= I
    MONTH= J
    DAY= K
C
    RETURN
    END
Example: YEAR = 1970, MONTH = 1, DAY = 1, JD = 2440588.
If input is 2440588

output should result.

Gregorian date for Julian date[JD] 2440588 is 01/01/1970

I just want to understand user defined function in awk here.

I guess this page should help you :slight_smile:

Thanks My problem is I didn't understand awk function, I am new to shell scripting, if someone explains I hope I can convert it.

This is how you simply define a function :slight_smile:

awk '
function JD2GD ( value )
{
#
# DO ALL YOUR CONVERSION MATH HERE
#
return (printf "%2d/%2d/%4d", d,m,y) #or you can just print here
}
{
GD=JD2GD($1);
print GD;
} ' file_with_juliandates

You would be well advised to follow PikK45's advice to look up an algorithm that works to calculate the Gregorian date from an astronomical Julian day number. The algorithm you originally posted in this thread doesn't work.

The only tricks to converting a FORTRAN subroutine to an awk function are to realize that awk performs divisions using floating point while FORTRAN uses integer division when dividing an integer by an integer and that all variables in awk are global except those declared to be local to a function (by including them in the function declaration arg list). (I use a tab (or two) between the input arguments that are required to be passed into the function to make it work and the list of local variables used by the function. If you don't like my convention for doing this, you should pick another method and use it consistently in any awk functions you write.)

You might also note that you had some variables (L and N) in your original FORTRAN code that were not declared.

The following awk script provides two awk functions (GDATE() and GDATE2()) that are straight translations of your original FORTRAN code and the algorithm specified by the page PikK45 suggested, respectively. If feeds two known astonomical Julian day numbers and prints the MONTH, DAY, and YEAR values set by both algorithms. The script is:

printf "%d\n" 2440588 2451545|awk '
# GDATE(JD)
# Compute and export YEAR, MONTH, and DAY of the Gregorian calendar date
# corresponding to the Julian date JD.
#
# Algorithm specified by Akshay Hegde
function GDATE(JD,      I, J, L, N) {
        L = JD + 68569
        N = int(4 * L / 146097)
        L = L - int((146097 * N + 3) / 4)
        I = int(4000 * (L + 1) / 1461001)
        L = L - 1461 * int(I / 4) + 31
        J = int(80 * L / 2447)
        DAY = L - int(2447 * J / 80)
        L = int(J / 11)
        MONTH = J + 2 - 12 * L
        YEAR = 100 * (N - 49) + I + L
}
# GDATE2(JD)
# Compute and export YEAR, MONTH, and DAY of the Gregorian calendar date
# corresponding to the Julian date JD.
#
# Algorithm specified by http://pmyers.pcug.org.au/General/JulianDates.htm
function GDATE2(j) {
        j = j - 1721119
        YEAR = int((4 * j - 1) / 146097)
        j = 4 * j - 1 - 146097 * YEAR 
        DAY = int(j / 4)
        j = int((4 * DAY + 3) / 1461)
        DAY = 4 * DAY + 3 - 1461 * j 
        DAY = int((DAY + 4) / 4)
        MONTH = int((5 * DAY - 3) / 153)
        DAY = 5 * DAY - 3 - 153 * MONTH 
        DAY = int((DAY + 5) / 5)
        YEAR = 100 * YEAR + j 
        if(MONTH < 10) MONTH = MONTH + 3
        else {
                MONTH = MONTH - 9
                YEAR = YEAR + 1
        }
}
{       GDATE($1)
        printf("Akshay Gregorian date for Julian date[JD] %d is %02d/%02d/%04d\n",
                $1, MONTH, DAY, YEAR)
        GDATE2($1)
        printf("PCUG Gregorian date for Julian date[JD] %d is %02d/%02d/%04d\n",
                $1, MONTH, DAY, YEAR)
}'

The output produced by this script is:

Akshay Gregorian date for Julian date[JD] 2440588 is 00/30/1971
PCUG Gregorian date for Julian date[JD] 2440588 is 01/01/1970
Akshay Gregorian date for Julian date[JD] 2451545 is 00/25/2003
PCUG Gregorian date for Julian date[JD] 2451545 is 01/01/2000

anyways thank you so much for teaching me how to use function in awk, I will start to write my own functions