May 23 2010

Simple Program to Calculate Julian Day and Sidereal Time

Posted by admin in general programming

Here’s the listing for a simple C program that prompts the user for his/her longitude (in decimal degrees, + for east of prime meridian and – for west of prime meridian). It utilizes built-in library functions and retrieves the local time and GMT time from the user’s computer then calculates the Julian Day and Sidereal Time. If the user enters ‘r’ or ‘R’, the program will re-calculate both values. Otherwise, the program exits normally.

The executable version of this program can be downloaded here.

Here is the complete program listing (or may be downloaded here):

#include
#include
#include

#define BASE_YEAR 1900

/* constant string arrays of the days of the week and the months of the year */
const char *days[] = {“Sunday”,”Monday”,”Tuesday”,”Wednesday”,”Thursday”,”Friday”,”Saturday”};
const char *months[] = {“January”,”February”,”March”,”April”,”May”,”June”,”July”,
“August”,”September”,”October”,”November”,”December”};

/* prototypes of functions defined below */
void display_time(char *, struct tm *);
double julian_date(struct tm *, int);
double sidereal_time(double, struct tm *, double);

int main(void)
{
double julian, sidereal;
float longitude;
double sid_hr, sid_mn, sid_sc;
char c;
time_t timer;

/* Print header */
printf(“\n”);
printf(” ***********************************************************************************\n”);
printf(” * This program displays the computer’s local time, the Greenwich Mean Time (GMT), *\n”);
printf(” * the Julian date, and local sidereal time (LST). The only input required is the *\n”);
printf(” * the user’s longitude. This must be entered in degrees and decimal degrees *\n”);
printf(” * (dd.ddd) east or west the prime meridian. For locations east of the prime *\n”);
printf(” * meridian, the value entered should be positive (+). For locations west of the *\n”);
printf(” * prime meridian, the value should be negative (-). *\n”);
printf(” ***********************************************************************************\n”);
printf(“\n”);

/* Prompt user for longitude in decimal degrees */
printf(” Enter your longitude: “);
scanf(“%f”,&longitude);

do
{
/* Display the user’s longitude */
printf(“\n Longitude: \t%0.2f “,fabs(longitude));
if (longitude < 0.0)
printf("West\n");
else
printf("East\n");
/* Load time struct with current data. Show local time and GMT */
timer=time(NULL);
display_time(" Local: ",localtime(&timer));
display_time(" GMT: ",gmtime(&timer));

/* Call Julian date function and display result */
julian = julian_date(gmtime(&timer),0);
printf(" Julian Date:\t%0.6f\n",julian);

/* Call Julian date function for present day at 0h GMT then call sidereal time function */
julian = julian_date(gmtime(&timer),1);
sidereal = sidereal_time(julian,gmtime(&timer),longitude);

/* Split sidereal time into hours, minutes, and seconds then display */
sid_mn = modf(sidereal,&sid_hr) * 60;
sid_sc = modf(sid_mn,&sid_mn) * 60;
modf(sid_sc,&sid_sc);
printf(" LST: \t%02.0f:%02.0f:%02.0f\n",sid_hr,sid_mn,sid_sc);

/* Read to end of line or end of buf to flush the input stream */
do {
c = fgetc(stdin);
} while ((c != '\n') && (c != EOF));

/* Wait for user to press ENTER to end or 'r' to repeat */
printf("\n\n Press ENTER to exit or 'R' plus ENTER to repeat: ");
scanf("%c",&c);
} while ((c == 'r') || (c == 'R'));

return 0;
}

/* Displays the time and date contained in the data of the struct that 'time' points to */
void display_time(char *str, struct tm *time)
{
printf("%s\t%s, %02d %s",str,*(days+(time->tm_wday)),time->tm_mday,*(months+(time->tm_mon)));
printf(” %d”,time->tm_year + BASE_YEAR);
printf(” %02d:%02d:%02d\n”,time->tm_hour,time->tm_min,time->tm_sec);
}

/* Calculate the Julian date for the date and time contained in the struct that ‘time’ points to. */
/* For ‘t_zero’ = 0, show the exact Julian date. For ‘t_zero’ = 1, show the Julian date at prior 0h GMT. */
double julian_date(struct tm *time, int t_zero)
{
int A,B;
int year = time->tm_year + BASE_YEAR;
int month = time->tm_mon + 1;
double julian_day, DD;

if (!t_zero)
DD = time->tm_mday + ((time->tm_hour + time->tm_min/60.0 + time->tm_sec/3600.0)/24.0);
else
DD = time->tm_mday;

if (month < 2)
{
year -= 1;
month += 12;
}

A = year/100;
B = 2 - A + A/4;

julian_day = floor(365.25 * year) + floor(30.6001*(month + 1.0)) + DD + 1720994.5 + B;

/* Return 'julian_day' in decimal format */
return julian_day;
}

/* Calculate and return the sidereal time given inputs of the Julian date at prior 0h GMT, */
/* current GMT as given in struct that 'time' points to, and the user-inputed longitude. */
double sidereal_time(double julian, struct tm *time, double lngtd)
{
double T, UT;
double local_sidereal;

/* Calculate decimal equivalent of current GMT */
UT = time->tm_hour;
UT += time->tm_min/60.0 + time->tm_sec/3600.0;

T = (julian – 2415020.0) / 36525.0;
local_sidereal = 6.6460656 + 2400.051262 * T + 0.00002581 * T * T;

/* Normalize ‘local_sidereal between 0 and 23 */
while (local_sidereal > 24)
{
local_sidereal -= 24;
}

local_sidereal += 1.002737908 * UT;
local_sidereal += lngtd / 15.0;

/* Normalize ‘local_sidereal’ between 0 and 23 */
if (local_sidereal < 0)
{
local_sidereal += 24;
}
else if (local_sidereal > 24)
{
local_sidereal -= 24;
}

/* Return LST in decimal format */
return local_sidereal;
}