SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
timeconvert.c
Go to the documentation of this file.
1/**
2 * @file timeconvert.c
3 * @brief Provides functions for converting and manipulating time representations, including leap year calculations, Julian day conversions, and epoch time breakdowns.
4 *
5 * @copyright
6 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
7 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
8 *
9 * @license
10 * This file is distributed under the terms of the Software License Agreement
11 * found in the file LICENSE included with this distribution.
12 *
13 * @author M. Borland, R. Soliday
14 */
15
16#include "mdb.h"
17#include "time_utils.h"
18#include <time.h>
19
20/**
21 * @brief Determines whether a given year is a leap year.
22 *
23 * Years below 100 are interpreted as 19xx if greater than 95, otherwise 20xx.
24 *
25 * @param year The year to evaluate.
26 * @return 1 if the year is a leap year, 0 if not, and -1 for invalid input.
27 */
28short IsLeapYear(short year) {
29 if (year < 0)
30 return -1;
31 year = year < 100 ? (year > 95 ? year + 1900 : year + 2000) : year;
32 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
33 return 1;
34 return 0;
35}
36
37/* days in each month for leap years, nonleap years */
38static const short DaysInMonths[2][12] = {
39 {
40 31,
41 28,
42 31,
43 30,
44 31,
45 30,
46 31,
47 31,
48 30,
49 31,
50 30,
51 31,
52 },
53 {
54 31,
55 29,
56 31,
57 30,
58 31,
59 30,
60 31,
61 31,
62 30,
63 31,
64 30,
65 31,
66 },
67};
68
69/**
70 * @brief Computes the Julian day number from a calendar date.
71 *
72 * @param month Month of the year (1-12).
73 * @param day Day of the month.
74 * @param year Year value.
75 * @param julianDay Pointer to store the resulting Julian day number.
76 * @return 1 on success, 0 on failure.
77 */
78short JulianDayFromMonthDay(short month, short day, short year, short *julianDay) {
79 short leapYear, jday, i, daysInMonth;
80
81 if (year <= 0 || month < 1 || month > 12 || day < 1 || !julianDay)
82 return 0;
83
84 leapYear = IsLeapYear(year);
85 daysInMonth = DaysInMonths[leapYear][month - 1];
86 if (day > daysInMonth)
87 return 0;
88
89 jday = day;
90 for (i = 1; i < month; i++)
91 jday += DaysInMonths[leapYear][i - 1];
92 *julianDay = jday;
93 return 1;
94}
95
96/**
97 * @brief Converts a Julian day number to month and day components.
98 *
99 * @param julianDay The Julian day number to convert.
100 * @param year Year corresponding to the Julian day.
101 * @param month Pointer to store the resulting month (1-12).
102 * @param day Pointer to store the resulting day of the month.
103 * @return 1 on success, 0 on failure.
104 */
105short MonthDayFromJulianDay(short julianDay, short year, short *month, short *day) {
106 short leapYear, sum, i, days;
107
108 if (julianDay < 0 || julianDay > 366 || year <= 0 || !month || !day)
109 return 0;
110 leapYear = IsLeapYear(year);
111 if ((leapYear == 0 && julianDay >= 365) || julianDay >= 366) {
112 *month = 12;
113 *day = 31;
114 return 1;
115 }
116
117 sum = 0;
118 for (i = 1; i <= 12; i++) {
119 days = DaysInMonths[leapYear][i - 1];
120 if (sum + days < julianDay) {
121 sum += days;
122 } else
123 break;
124 }
125 *month = i;
126 *day = julianDay - sum;
127 return 1;
128}
129
130/**
131 * @brief Breaks down epoch time into its constituent components.
132 *
133 * This function decomposes epoch time into year, Julian day, month, day, and fractional hour components.
134 *
135 * @param year Pointer to store the year.
136 * @param jDay Pointer to store the Julian day.
137 * @param month Pointer to store the month.
138 * @param day Pointer to store the day.
139 * @param hour Pointer to store the fractional hour.
140 * @param epochTime The epoch time to be broken down.
141 * @return Returns 1 on success, 0 on failure.
142 */
143short TimeEpochToBreakdown(short *year, short *jDay, short *month, short *day, double *hour, double epochTime) {
144 struct tm timeBreakdown;
145 double dayStartTime;
146 short lyear, ljDay, lhour;
147 time_t theTime;
148 theTime = epochTime;
149 if (!mdb_localtime_copy(&theTime, &timeBreakdown))
150 return 0;
151 lyear = timeBreakdown.tm_year + 1900;
152 ljDay = timeBreakdown.tm_yday + 1;
153 lhour = timeBreakdown.tm_hour;
154 if (year)
155 *year = lyear;
156 if (jDay)
157 *jDay = ljDay;
158 if (month)
159 *month = timeBreakdown.tm_mon + 1;
160 if (day)
161 *day = timeBreakdown.tm_mday;
162 if (hour) {
163 /* go through some contortions to preserve fractional seconds */
164 TimeBreakdownToEpoch(lyear, ljDay, (short)0, (short)0, (double)0.0, &dayStartTime);
165 *hour = (epochTime - dayStartTime) / 3600;
166 if (((short)*hour) != lhour) {
167 /* daylight savings time problem? */
168 *hour = *hour + lhour - ((short)*hour);
169 }
170 }
171 return 1;
172}
173
174/**
175 * @brief Converts epoch time to a formatted text string.
176 *
177 * This function formats epoch time into a human-readable string in the format "YYYY/MM/DD HH:MM:SS.FFFF".
178 *
179 * @param text Buffer to store the formatted time string.
180 * @param epochTime The epoch time to be converted.
181 * @return Returns 1 on success, 0 on failure.
182 */
183short TimeEpochToText(char *text, double epochTime) {
184 short year, jDay, month, day, hr, min;
185 double dayTime, sec;
186 if (!TimeEpochToBreakdown(&year, &jDay, &month, &day, &dayTime, epochTime))
187 return 0;
188 hr = dayTime;
189 min = 60 * (dayTime - hr);
190 sec = 3600.0 * dayTime - (3600.0 * hr + 60.0 * min);
191 sprintf(text, "%04hd/%02hd/%02hd %02hd:%02hd:%07.4f",
192 year, month, day, hr, min, sec);
193 return 1;
194}
195
196/**
197 * @brief Converts a broken-down time into epoch time.
198 *
199 * This function takes individual time components and converts them into epoch time.
200 * It handles both Julian day and standard month/day formats based on the input.
201 *
202 * @param year The year.
203 * @param jDay The Julian day number.
204 * @param month The month.
205 * @param day The day of the month.
206 * @param hour The fractional hour.
207 * @param epochTime Pointer to store the resulting epoch time.
208 * @return Returns 1 on success, 0 on failure.
209 */
210short TimeBreakdownToEpoch(short year, short jDay, short month, short day, double hour, double *epochTime) {
211 struct tm timeBreakdown;
212 short imin, ihour;
213 double fsec, fmin;
214
215 if (!epochTime)
216 return 0;
217 memset((char *)&timeBreakdown, 0, sizeof(timeBreakdown));
218 if (year > 100)
219 timeBreakdown.tm_year = year - 1900;
220 else
221 timeBreakdown.tm_year = year;
222 if (jDay) {
223 short iday, imonth;
224 if (!MonthDayFromJulianDay(jDay, year, &imonth, &iday)) {
225 return 0;
226 }
227 timeBreakdown.tm_mday = iday;
228 timeBreakdown.tm_mon = imonth - 1;
229 } else {
230 timeBreakdown.tm_mday = day;
231 timeBreakdown.tm_mon = month - 1;
232 }
233 /* Break floating-point hours into integer H:M:S plus fractional seconds */
234 ihour = timeBreakdown.tm_hour = hour;
235 imin = timeBreakdown.tm_min = fmin = 60 * (hour - ihour);
236 timeBreakdown.tm_sec = fsec = 60 * (fmin - imin);
237 fsec -= timeBreakdown.tm_sec;
238 timeBreakdown.tm_isdst = -1;
239#if defined(SUNOS4)
240 *epochTime = timelocal(&timeBreakdown) + fsec;
241#else
242 *epochTime = mktime(&timeBreakdown) + fsec;
243#endif
244 return 1;
245}
short TimeEpochToBreakdown(short *year, short *jDay, short *month, short *day, double *hour, double epochTime)
Breaks down epoch time into its constituent components.
short IsLeapYear(short year)
Determines whether a given year is a leap year.
Definition timeconvert.c:28
short TimeBreakdownToEpoch(short year, short jDay, short month, short day, double hour, double *epochTime)
Converts a broken-down time into epoch time.
short MonthDayFromJulianDay(short julianDay, short year, short *month, short *day)
Converts a Julian day number to month and day components.
short TimeEpochToText(char *text, double epochTime)
Converts epoch time to a formatted text string.
short JulianDayFromMonthDay(short month, short day, short year, short *julianDay)
Computes the Julian day number from a calendar date.
Definition timeconvert.c:78