From 2dca19e6f90fc2cb7deebb6e88def9a9d413362d Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 7 Feb 2013 16:29:36 +0100 Subject: [PATCH] added support for more planets and the earth's moon --- src/Makefile.am | 2 +- src/Makefile.in | 7 +- src/geonames_main.c | 2 +- src/objects.c | 166 ++++++++++++++++++++++++++++++++++ src/objects.h | 75 ++++++++++++++++ src/sun_main.c | 212 +++++++++++++++++++++++++++----------------- 6 files changed, 378 insertions(+), 86 deletions(-) create mode 100644 src/objects.c create mode 100644 src/objects.h diff --git a/src/Makefile.am b/src/Makefile.am index 8689df7..91f8d56 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ bin_PROGRAMS = sun -sun_SOURCES = sun_main.c +sun_SOURCES = sun_main.c objects.c sun_LDADD = -lm -lnova if GEONAMES_SUPPORT diff --git a/src/Makefile.in b/src/Makefile.in index 104993c..0ec5476 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -71,9 +71,9 @@ am__geonames_SOURCES_DIST = geonames_main.c geonames.c geonames_OBJECTS = $(am_geonames_OBJECTS) am__DEPENDENCIES_1 = @GEONAMES_SUPPORT_TRUE@geonames_DEPENDENCIES = $(am__DEPENDENCIES_1) -am__sun_SOURCES_DIST = sun_main.c geonames.c +am__sun_SOURCES_DIST = sun_main.c objects.c geonames.c @GEONAMES_SUPPORT_TRUE@am__objects_1 = geonames.$(OBJEXT) -am_sun_OBJECTS = sun_main.$(OBJEXT) $(am__objects_1) +am_sun_OBJECTS = sun_main.$(OBJEXT) objects.$(OBJEXT) $(am__objects_1) sun_OBJECTS = $(am_sun_OBJECTS) @GEONAMES_SUPPORT_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) sun_DEPENDENCIES = $(am__DEPENDENCIES_2) @@ -183,7 +183,7 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -sun_SOURCES = sun_main.c $(am__append_1) +sun_SOURCES = sun_main.c objects.c $(am__append_1) sun_LDADD = -lm -lnova $(am__append_2) @GEONAMES_SUPPORT_TRUE@geonames_SOURCES = geonames_main.c geonames.c @GEONAMES_SUPPORT_TRUE@geonames_LDADD = $(DEPS_GEONAMES_LIBS) @@ -280,6 +280,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/geonames.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/geonames_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/objects.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sun_main.Po@am__quote@ .c.o: diff --git a/src/geonames_main.c b/src/geonames_main.c index 408ac75..36d4d62 100644 --- a/src/geonames_main.c +++ b/src/geonames_main.c @@ -44,7 +44,7 @@ int main(int argc, char *argv[]) { int ret = geonames_lookup(name, &res, result_name, 32); if (ret == EXIT_SUCCESS) { - printf("%s is at (%.4f, %.4f)\r\n", result_name, res.lat, res.lon); + printf("%s is at (%.4f, %.4f)\r\n", result_name, res.lat, res.lng); } free(result_name); diff --git a/src/objects.c b/src/objects.c new file mode 100644 index 0000000..2b1b9e6 --- /dev/null +++ b/src/objects.c @@ -0,0 +1,166 @@ +/** + * libnova bindings + * + * @copyright 2012 Steffen Vogel + * @license http://www.gnu.org/licenses/gpl.txt GNU Public License + * @author Steffen Vogel + * @link http://www.steffenvogel.de/2012/03/14/cron-jobs-fur-sonnenauf-untergang/ + */ +/* + * This file is part of sun + * + * sun is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * sun is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with sun. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "objects.h" + +void object_pos(enum object obj, double jd, struct ln_lnlat_posn *obs, struct ln_equ_posn *equ, struct ln_hrz_posn *hrz, double *diam, double *dist) { + switch (obj) { + case OBJECT_SUN: return object_pos_sun(jd, obs, equ, hrz, diam, dist); + case OBJECT_MOON: return object_pos_moon(jd, obs, equ, hrz, diam, dist); + case OBJECT_MARS: return object_pos_mars(jd, obs, equ, hrz, diam, dist); + case OBJECT_NEPTUNE: return object_pos_neptune(jd, obs, equ, hrz, diam, dist); + case OBJECT_JUPITER: return object_pos_jupiter(jd, obs, equ, hrz, diam, dist); + case OBJECT_MERCURY: return object_pos_mercury(jd, obs, equ, hrz, diam, dist); + case OBJECT_URANUS: return object_pos_uranus(jd, obs, equ, hrz, diam, dist); + case OBJECT_SATURN: return object_pos_saturn(jd, obs, equ, hrz, diam, dist); + case OBJECT_VENUS: return object_pos_venus(jd, obs, equ, hrz, diam, dist); + case OBJECT_PLUTO: return object_pos_pluto(jd, obs, equ, hrz, diam, dist); + } +} + +int object_rst(enum object obj, double jd, double horizon, struct ln_lnlat_posn *obs, struct ln_rst_time *rst) { + switch (obj) { + case OBJECT_SUN: return ln_get_solar_rst_horizon(jd, obs, horizon, rst); + case OBJECT_MOON: return ln_get_lunar_rst(jd, obs, rst); + case OBJECT_MARS: return ln_get_mars_rst(jd, obs, rst); + case OBJECT_NEPTUNE: return ln_get_neptune_rst(jd, obs, rst); + case OBJECT_JUPITER: return ln_get_jupiter_rst(jd, obs, rst); + case OBJECT_MERCURY: return ln_get_mercury_rst(jd, obs, rst); + case OBJECT_URANUS: return ln_get_uranus_rst(jd, obs, rst); + case OBJECT_SATURN: return ln_get_saturn_rst(jd, obs, rst); + case OBJECT_VENUS: return ln_get_venus_rst(jd, obs, rst); + case OBJECT_PLUTO: return ln_get_pluto_rst(jd, obs, rst); + } +} + +enum object object_from_name(const char *name, bool casesen) { + // TODO case sensivity + + if (strcmp(name, "sun") == 0) return OBJECT_SUN; + else if (strcmp(name, "moon") == 0) return OBJECT_MOON; + else if (strcmp(name, "mars") == 0) return OBJECT_MARS; + else if (strcmp(name, "neptune") == 0) return OBJECT_NEPTUNE; + else if (strcmp(name, "jupiter") == 0) return OBJECT_JUPITER; + else if (strcmp(name, "mercury") == 0) return OBJECT_MERCURY; + else if (strcmp(name, "uranus") == 0) return OBJECT_URANUS; + else if (strcmp(name, "saturn") == 0) return OBJECT_SATURN; + else if (strcmp(name, "venus") == 0) return OBJECT_VENUS; + else if (strcmp(name, "pluto") == 0) return OBJECT_PLUTO; + else return OBJECT_INVALID; +} + +void object_pos_sun(double jd, struct ln_lnlat_posn *obs, struct ln_equ_posn *equ, struct ln_hrz_posn *hrz, double *diam, double *dist) { + ln_get_solar_equ_coords(jd, equ); + ln_get_hrz_from_equ(equ, obs, jd, hrz); + + *dist = ln_get_earth_solar_dist(jd); + *diam = ln_get_solar_sdiam(jd); +} + +void object_pos_moon(double jd, struct ln_lnlat_posn *obs, struct ln_equ_posn *equ, struct ln_hrz_posn *hrz, double *diam, double *dist) { + ln_get_lunar_equ_coords(jd, equ); + ln_get_hrz_from_equ(equ, obs, jd, hrz); + + *dist = ln_get_lunar_earth_dist(jd) / AU_METERS; + *diam = ln_get_lunar_sdiam(jd); +} + +void object_pos_mars(double jd, struct ln_lnlat_posn *obs, struct ln_equ_posn *equ, struct ln_hrz_posn *hrz, double *diam, double *dist) { + ln_get_mars_equ_coords(jd, equ); + ln_get_hrz_from_equ(equ, obs, jd, hrz); + + *dist = ln_get_mars_earth_dist(jd); + *diam = ln_get_mars_sdiam(jd); +} + +void object_pos_neptune(double jd, struct ln_lnlat_posn *obs, struct ln_equ_posn *equ, struct ln_hrz_posn *hrz, double *diam, double *dist) { + ln_get_neptune_equ_coords(jd, equ); + ln_get_hrz_from_equ(equ, obs, jd, hrz); + + *dist = ln_get_neptune_earth_dist(jd); + *diam = ln_get_neptune_sdiam(jd); +} + +void object_pos_jupiter(double jd, struct ln_lnlat_posn *obs, struct ln_equ_posn *equ, struct ln_hrz_posn *hrz, double *diam, double *dist) { + ln_get_jupiter_equ_coords(jd, equ); + ln_get_hrz_from_equ(equ, obs, jd, hrz); + + *dist = ln_get_jupiter_earth_dist(jd); + *diam = ln_get_jupiter_equ_sdiam(jd); +} + +void object_pos_mercury(double jd, struct ln_lnlat_posn *obs, struct ln_equ_posn *equ, struct ln_hrz_posn *hrz, double *diam, double *dist) { + ln_get_mercury_equ_coords(jd, equ); + ln_get_hrz_from_equ(equ, obs, jd, hrz); + + *dist = ln_get_mercury_earth_dist(jd); + *diam = ln_get_mercury_sdiam(jd); +} + +void object_pos_uranus(double jd, struct ln_lnlat_posn *obs, struct ln_equ_posn *equ, struct ln_hrz_posn *hrz, double *diam, double *dist) { + ln_get_uranus_equ_coords(jd, equ); + ln_get_hrz_from_equ(equ, obs, jd, hrz); + + *dist = ln_get_uranus_earth_dist(jd); + *diam = ln_get_uranus_sdiam(jd); +} + +void object_pos_saturn(double jd, struct ln_lnlat_posn *obs, struct ln_equ_posn *equ, struct ln_hrz_posn *hrz, double *diam, double *dist) { + ln_get_saturn_equ_coords(jd, equ); + ln_get_hrz_from_equ(equ, obs, jd, hrz); + + *dist = ln_get_saturn_earth_dist(jd); + *diam = ln_get_saturn_equ_sdiam(jd); +} + +void object_pos_venus(double jd, struct ln_lnlat_posn *obs, struct ln_equ_posn *equ, struct ln_hrz_posn *hrz, double *diam, double *dist) { + ln_get_venus_equ_coords(jd, equ); + ln_get_hrz_from_equ(equ, obs, jd, hrz); + + *dist = ln_get_venus_earth_dist(jd); + *diam = ln_get_venus_sdiam(jd); +} + +void object_pos_pluto(double jd, struct ln_lnlat_posn *obs, struct ln_equ_posn *equ, struct ln_hrz_posn *hrz, double *diam, double *dist) { + ln_get_pluto_equ_coords(jd, equ); + ln_get_hrz_from_equ(equ, obs, jd, hrz); + + *dist = ln_get_pluto_earth_dist(jd); + *diam = ln_get_pluto_sdiam(jd); +} diff --git a/src/objects.h b/src/objects.h new file mode 100644 index 0000000..3f8ef59 --- /dev/null +++ b/src/objects.h @@ -0,0 +1,75 @@ +/** + * libnova bindings + * + * @copyright 2012 Steffen Vogel + * @license http://www.gnu.org/licenses/gpl.txt GNU Public License + * @author Steffen Vogel + * @link http://www.steffenvogel.de/2012/03/14/cron-jobs-fur-sonnenauf-untergang/ + */ +/* + * This file is part of sun + * + * sun is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * sun is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with sun. If not, see . + */ + +#ifndef _OBJECTS_H_ +#define _OBJECTS_H_ + +#include + +#include + +#define AU_METERS 149597870.7 + +enum object { + OBJECT_INVALID, + OBJECT_SUN, + OBJECT_MOON, + OBJECT_MARS, + OBJECT_NEPTUNE, + OBJECT_JUPITER, + OBJECT_MERCURY, + OBJECT_URANUS, + OBJECT_SATURN, + OBJECT_VENUS, + OBJECT_PLUTO +}; + +struct object_infos { + struct ln_rst_time *rst; + + struct ln_lnlat_posn *obs; + struct ln_equ_posn *equ; + struct ln_hrz_posn *hrz; + double *diam; + double *dist; +}; + +enum object object_from_name(const char *name, bool casesen); + +void object_pos(enum object obj, double jd, struct object_details *details); +int object_rst(enum object obj, double jd, double horizon, struct ln_lnlat_posn *obs, struct ln_rst_time *rst); + +void object_pos_sun(double jd, struct object_details *details); +void object_pos_moon(double jd, struct object_details *details); +void object_pos_mars(double jd, struct object_details *details); +void object_pos_neptune(double jd, struct object_details *details); +void object_pos_jupiter(double jd, struct object_details *details); +void object_pos_mercury(double jd, struct object_details *details); +void object_pos_uranus(double jd, struct object_details *details); +void object_pos_saturn(double jd, struct object_details *details); +void object_pos_venus(double jd, struct object_details *details); +void object_pos_pluto(double jd, struct object_details *details); + +#endif /* _OBJECTS_H_ */ diff --git a/src/sun_main.c b/src/sun_main.c index 2c5e561..7261b8b 100644 --- a/src/sun_main.c +++ b/src/sun_main.c @@ -39,34 +39,46 @@ #include #include +#include + #include -#include +#include #include "../config.h" +#include "objects.h" -enum mode { INVALID, RISE, SET, TRANSIT, DAYTIME, NIGHTTIME }; +enum mode { + MODE_NOW, + MODE_RISE, + MODE_SET, + MODE_TRANSIT +}; extern long timezone; static struct option long_options[] = { - {"horizon", required_argument, 0, 't'}, - {"date", required_argument, 0, 'd'}, + {"object", required_argument, 0, 'p'}, + {"horizon", required_argument, 0, 'H'}, + {"time", required_argument, 0, 't'}, + {"moment", required_argument, 0, 'm'}, {"format", required_argument, 0, 'f'}, {"lat", required_argument, 0, 'a'}, {"lon", required_argument, 0, 'o'}, #ifdef GEONAMES_SUPPORT {"query", required_argument, 0, 'q'}, #endif - {"zone", required_argument, 0, 'z'}, + {"timezone", required_argument, 0, 'z'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'v'}, {0} }; static char *long_options_descs[] = { - "use special twilight (nautic|civil|astronomical)", - "calculcate for specified date (eg. 2011-12-25)", - "output format (eg. %H:%M:%S)", + "calculate for given object/planet", + "calculate rise/set with given twilight (nautic|civil|astronomical)", + "calculate with given time (eg. 2011-12-25)", + "use rise/set/transit time for position calculation", + "output format (see strftime (3))", "geographical latitude (-90° to 90°)", "geographical longitude (-180° to 180°)", #ifdef GEONAMES_SUPPORT @@ -83,8 +95,7 @@ void version () { } void usage() { - printf("Usage:\n sun mode [options]\n\n"); - printf(" mode is one of: rise, set, transit, daytime, nighttime\n\n"); + printf("Usage:\n %s [options]\n\n", PACKAGE_NAME); printf("Options:\n"); struct option *op = long_options; @@ -133,41 +144,32 @@ int main(int argc, char *argv[]) { char *query = NULL; bool error = false; - enum mode mode = INVALID; + enum mode mode = MODE_NOW; + enum object obj = OBJECT_INVALID; - double julian; + double jd; struct tm date = { 0 }; struct ln_rst_time rst; - struct ln_lnlat_posn observer = { DBL_MAX, DBL_MAX }; + struct ln_lnlat_posn obs = { DBL_MAX, DBL_MAX }; tzset(); /* default time: now */ - julian = ln_get_julian_from_sys(); + jd = ln_get_julian_from_sys(); - /* parse mode */ - if (argc > 1 && argv[1][0] != '-') { - if (strcmp(argv[1], "rise") == 0) mode = RISE; - else if (strcmp(argv[1], "set") == 0) mode = SET; - else if (strcmp(argv[1], "transit") == 0) mode = TRANSIT; - else if (strcmp(argv[1], "daytime") == 0) mode = DAYTIME; - else if (strcmp(argv[1], "nighttime") == 0) mode = NIGHTTIME; - - /* skip mode parameter for following getopt() */ - argc--; - argv++; - } + /* parse planet/obj */ + obj = object_from_name(basename(argv[0]), false); /* parse command line arguments */ while (1) { int optidx; - int c = getopt_long(argc, argv, "+hvt:d:f:a:o:q:z:", long_options, &optidx); + int c = getopt_long(argc, argv, "+hvt:d:f:a:o:q:z:p:", long_options, &optidx); /* detect the end of the options. */ if (c == -1) break; switch (c) { - case 't': + case 'H': if (strcmp(optarg, "civil") == 0) { horizon = LN_SOLAR_CIVIL_HORIZON; } @@ -183,14 +185,14 @@ int main(int argc, char *argv[]) { } break; - case 'd': + case 't': if (strptime(optarg, "%Y-%m-%d", &date) == NULL) { fprintf(stderr, "invalid date: %s\n", optarg); error = true; } else { time_t t = mktime(&date); - julian = ln_get_julian_from_timet(&t); + jd = ln_get_julian_from_timet(&t); #ifdef DEBUG char date_str[64]; @@ -201,16 +203,27 @@ int main(int argc, char *argv[]) { } break; + case 'm': + if (strcmp(optarg, "now") == 0) mode = MODE_NOW; + else if (strcmp(optarg, "rise") == 0) mode = MODE_RISE; + else if (strcmp(optarg, "set") == 0) mode = MODE_SET; + else if (strcmp(optarg, "transit") == 0) mode = MODE_TRANSIT; + else { + fprintf(stderr, "invalid moment: %s\n", optarg); + error = true; + } + break; + case 'f': format = strdup(optarg); break; case 'a': - observer.lat = strtod(optarg, NULL); + obs.lat = strtod(optarg, NULL); break; case 'o': - observer.lng = strtod(optarg, NULL); + obs.lng = strtod(optarg, NULL); break; #ifdef GEONAMES_SUPPORT case 'q': @@ -218,6 +231,10 @@ int main(int argc, char *argv[]) { break; #endif + case 'p': + obj = object_from_name(optarg, false); + break; + case 'z': timezone = -3600 * atoi(optarg); break; @@ -237,26 +254,26 @@ int main(int argc, char *argv[]) { } } - /* validate mode */ - if (mode == INVALID) { - fprintf(stderr, "invalid mode\n"); + /* validate obj */ + if (obj == OBJECT_INVALID) { + fprintf(stderr, "invalid object\n"); error = true; } #ifdef GEONAMES_SUPPORT /* lookup place at http://geonames.org */ - if (query && geonames_lookup(query, (struct pos *) &observer, NULL, 0) != 0) { + if (query && geonames_lookup(query, (struct pos *) &obs, NULL, 0) != 0) { fprintf(stderr, "failed to lookup location: %s\n", query); error = true; } #endif - /* validate coordinates */ - if (fabs(observer.lat) > 90) { + /* validate observer coordinates */ + if (fabs(obs.lat) > 90) { fprintf(stderr, "invalid latitude\n"); error = true; } - if (fabs(observer.lng) > 180) { + if (fabs(obs.lng) > 180) { fprintf(stderr, "invalid longitude\n"); error = true; } @@ -271,62 +288,95 @@ int main(int argc, char *argv[]) { #ifdef DEBUG char date_str[64]; time_t t; - ln_get_timet_from_julian(julian, &t); + ln_get_timet_from_julian(jd, &t); - strftime(date_str, 64, "%Y-%m-%d", gmtime(&t)); + strftime(date_str, 64, "%Y-%m-%d %H:%M:%S", gmtime(&t)); printf("calculate for: %s\n", date_str); - printf("for position: %f, %f\n", observer.lat, observer.lng); + printf("calculate for jd: %f\n", jd); + printf("for position: %f, %f\n", obs.lat, obs.lng); + printf("for object: %d\n", obj); printf("with horizon: %f\n", horizon); printf("with timezone: UTC +%dh\n", timezone / -3600); #endif - if (ln_get_solar_rst_horizon(julian, &observer, horizon, &rst) == 1) { - fprintf(stderr, "sun is circumpolar\n"); + char result_str[64]; + struct tm result_date; + struct ln_date result_ln; + + if (object_rst(obj, jd, horizon, &obs, &rst) == 1) { + + fprintf(stderr, "object is circumpolar\n"); return EXIT_CIRCUMPOLAR; } + + switch (mode) { + case MODE_RISE: jd = rst.rise; break; + case MODE_SET: jd = rst.set; break; + case MODE_TRANSIT: jd = rst.transit; break; + case MODE_DAYTIME: jd = rst.set - rst.rise; break; + case MODE_NIGHTTIME: jd = rst.set - rst.rise; break; + case MODE_INVALID: break; + } + + if (mode == MODE_DAYTIME || mode == MODE_NIGHTTIME) { + ln_get_date(jd - 0.5, &result_ln); + + if (strstr(format, "%s") != NULL) { + char timestamp_str[16]; + int seconds = round(jd * 86400); + snprintf(timestamp_str, sizeof(timestamp_str), "%lu", seconds); + format = strreplace(format, "%s", timestamp_str); + } + + result_date.tm_year = -1900; + result_date.tm_mon = -1; + result_date.tm_mday = 0; + } else { - double result_jd; - char result_str[64]; - struct tm result_date; - struct ln_date result_ln; + // calculate position + struct ln_equ_posn result_equ; + struct ln_hrz_posn result_hrz; + double result_dist; + double result_diam; - switch (mode) { - case RISE: result_jd = rst.rise; break; - case SET: result_jd = rst.set; break; - case TRANSIT: result_jd = rst.transit; break; - case DAYTIME: result_jd = rst.set - rst.rise; break; - case NIGHTTIME: result_jd = rst.set - rst.rise; break; + object_pos(obj, jd, &obs, &result_equ, &result_hrz, &result_diam, &result_dist); + + struct ln_hms ra; + ln_deg_to_hms(result_equ.ra, &ra); + + double az = result_hrz.az + 180; + az -= (int) (az / 360) * 360; + + printf("diam = %f\n", result_diam); + printf("dist au = %f\n", result_dist); + printf("dist km = %f\n", AU_METERS * result_dist); + printf("az = %s\n", ln_get_humanr_location(az)); + printf("alt = %s\n", ln_get_humanr_location(result_hrz.alt)); + printf("ra = %dh%dm%fs\n", ra.hours, ra.minutes, ra.seconds); + printf("dec = %s\n", ln_get_humanr_location(result_equ.dec)); + + /*if (strstr(format, "%R") != NULL) { + snprintf(timestamp_str, sizeof(timestamp_str), "%lu", seconds); + format = strreplace(format, "%s", timestamp_str); } + if (strstr(format, "%E") != NULL) { + snprintf(timestamp_str, sizeof(timestamp_str), "%lu", seconds); + format = strreplace(format, "%s", timestamp_str); + }*/ - if (mode == DAYTIME || mode == NIGHTTIME) { - ln_get_date(result_jd - 0.5, &result_ln); + ln_get_date(jd - timezone / 86400.0, &result_ln); - if (strstr(format, "%s") != NULL) { - char timestamp_str[16]; - int seconds = round(result_jd * 86400); - snprintf(timestamp_str, sizeof(timestamp_str), "%lu", seconds); - format = strreplace(format, "%s", timestamp_str); - } + result_date.tm_year = result_ln.years - 1900; + result_date.tm_mon = result_ln.months - 1; + result_date.tm_mday = result_ln.days; + } - result_date.tm_year = -1900; - result_date.tm_mon = -1; - result_date.tm_mday = 0; - } - else { - ln_get_date(result_jd - timezone / 86400.0, &result_ln); + result_date.tm_hour = result_ln.hours; + result_date.tm_min = result_ln.minutes; + result_date.tm_sec = result_ln.seconds; - result_date.tm_year = result_ln.years - 1900; - result_date.tm_mon = result_ln.months - 1; - result_date.tm_mday = result_ln.days; - } + strftime(result_str, 64, format, &result_date); + printf("%s\n", result_str); - result_date.tm_hour = result_ln.hours; - result_date.tm_min = result_ln.minutes; - result_date.tm_sec = result_ln.seconds; - - strftime(result_str, 64, format, &result_date); - printf("%s\n", result_str); - - return EXIT_SUCCESS; - } + return EXIT_SUCCESS; }