SDDSlib
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.h>
18
19short IsLeapYear(short year) {
20 if (year < 0)
21 return -1;
22 year = year < 100 ? (year > 95 ? year + 1900 : year + 2000) : year;
23 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
24 return 1;
25 return 0;
26}
27
28/* days in each month for leap years, nonleap years */
29static short DaysInMonths[2][12] = {
30 {
31 31,
32 28,
33 31,
34 30,
35 31,
36 30,
37 31,
38 31,
39 30,
40 31,
41 30,
42 31,
43 },
44 {
45 31,
46 29,
47 31,
48 30,
49 31,
50 30,
51 31,
52 31,
53 30,
54 31,
55 30,
56 31,
57 },
58};
59
60short JulianDayFromMonthDay(short month, short day, short year, short *julianDay) {
61 short leapYear, jday, i, daysInMonth;
62
63 if (year <= 0 || month < 1 || month > 12 || day < 1 || !julianDay)
64 return 0;
65
66 leapYear = IsLeapYear(year);
67 daysInMonth = DaysInMonths[leapYear][month - 1];
68 if (day > daysInMonth)
69 return 0;
70
71 jday = day;
72 for (i = 1; i < month; i++)
73 jday += DaysInMonths[leapYear][i - 1];
74 *julianDay = jday;
75 return 1;
76}
77
78short MonthDayFromJulianDay(short julianDay, short year, short *month, short *day) {
79 short leapYear, sum, i, days;
80
81 if (julianDay < 0 || julianDay > 366 || year <= 0 || !month || !day)
82 return 0;
83 leapYear = IsLeapYear(year);
84 if ((leapYear == 0 && julianDay >= 365) || julianDay >= 366) {
85 *month = 12;
86 *day = 31;
87 return 1;
88 }
89
90 sum = 0;
91 for (i = 1; i <= 12; i++) {
92 days = DaysInMonths[leapYear][i - 1];
93 if (sum + days < julianDay) {
94 sum += days;
95 } else
96 break;
97 }
98 *month = i;
99 *day = julianDay - sum;
100 return 1;
101}
102
103#include <time.h>
104/**
105 * @brief Breaks down epoch time into its constituent components.
106 *
107 * This function decomposes epoch time into year, Julian day, month, day, and fractional hour components.
108 *
109 * @param year Pointer to store the year.
110 * @param jDay Pointer to store the Julian day.
111 * @param month Pointer to store the month.
112 * @param day Pointer to store the day.
113 * @param hour Pointer to store the fractional hour.
114 * @param epochTime The epoch time to be broken down.
115 * @return Returns 1 on success, 0 on failure.
116 */
117short TimeEpochToBreakdown(short *year, short *jDay, short *month, short *day, double *hour, double epochTime) {
118 struct tm *timeBreakdown;
119 double dayStartTime;
120 short lyear, ljDay, lhour;
121 time_t theTime;
122 theTime = epochTime;
123 if (!(timeBreakdown = localtime(&theTime)))
124 return 0;
125 lyear = timeBreakdown->tm_year + 1900;
126 ljDay = timeBreakdown->tm_yday + 1;
127 lhour = timeBreakdown->tm_hour;
128 if (year)
129 *year = lyear;
130 if (jDay)
131 *jDay = ljDay;
132 if (month)
133 *month = timeBreakdown->tm_mon + 1;
134 if (day)
135 *day = timeBreakdown->tm_mday;
136 if (hour) {
137 /* go through some contortions to preserve fractional seconds */
138 TimeBreakdownToEpoch(lyear, ljDay, (short)0, (short)0, (double)0.0, &dayStartTime);
139 *hour = (epochTime - dayStartTime) / 3600;
140 if (((short)*hour) != lhour) {
141 /* daylight savings time problem? */
142 *hour = *hour + lhour - ((short)*hour);
143 }
144 }
145 return 1;
146}
147
148/**
149 * @brief Converts epoch time to a formatted text string.
150 *
151 * This function formats epoch time into a human-readable string in the format "YYYY/MM/DD HH:MM:SS.FFFF".
152 *
153 * @param text Buffer to store the formatted time string.
154 * @param epochTime The epoch time to be converted.
155 * @return Returns 1 on success, 0 on failure.
156 */
157short TimeEpochToText(char *text, double epochTime) {
158 short year, jDay, month, day, hr, min;
159 double dayTime, sec;
160 if (!TimeEpochToBreakdown(&year, &jDay, &month, &day, &dayTime, epochTime))
161 return 0;
162 hr = dayTime;
163 min = 60 * (dayTime - hr);
164 sec = 3600.0 * dayTime - (3600.0 * hr + 60.0 * min);
165 sprintf(text, "%04hd/%02hd/%02hd %02hd:%02hd:%07.4f",
166 year, month, day, hr, min, sec);
167 return 1;
168}
169
170/**
171 * @brief Converts a broken-down time into epoch time.
172 *
173 * This function takes individual time components and converts them into epoch time.
174 * It handles both Julian day and standard month/day formats based on the input.
175 *
176 * @param year The year.
177 * @param jDay The Julian day number.
178 * @param month The month.
179 * @param day The day of the month.
180 * @param hour The fractional hour.
181 * @param epochTime Pointer to store the resulting epoch time.
182 * @return Returns 1 on success, 0 on failure.
183 */
184short TimeBreakdownToEpoch(short year, short jDay, short month, short day, double hour, double *epochTime) {
185 struct tm timeBreakdown;
186 short imin, ihour;
187 double fsec, fmin;
188
189 if (!epochTime)
190 return 0;
191 memset((char *)&timeBreakdown, 0, sizeof(timeBreakdown));
192 if (year > 100)
193 timeBreakdown.tm_year = year - 1900;
194 else
195 timeBreakdown.tm_year = year;
196 if (jDay) {
197 short iday, imonth;
198 if (!MonthDayFromJulianDay(jDay, year, &imonth, &iday)) {
199 return 0;
200 }
201 timeBreakdown.tm_mday = iday;
202 timeBreakdown.tm_mon = imonth - 1;
203 } else {
204 timeBreakdown.tm_mday = day;
205 timeBreakdown.tm_mon = month - 1;
206 }
207 /* Break floating-point hours into integer H:M:S plus fractional seconds */
208 ihour = timeBreakdown.tm_hour = hour;
209 imin = timeBreakdown.tm_min = fmin = 60 * (hour - ihour);
210 timeBreakdown.tm_sec = fsec = 60 * (fmin - imin);
211 fsec -= timeBreakdown.tm_sec;
212 timeBreakdown.tm_isdst = -1;
213#if defined(SUNOS4)
214 *epochTime = timelocal(&timeBreakdown) + fsec;
215#else
216 *epochTime = mktime(&timeBreakdown) + fsec;
217#endif
218 return 1;
219}
short TimeEpochToBreakdown(short *year, short *jDay, short *month, short *day, double *hour, double epochTime)
Breaks down epoch time into its constituent components.
short TimeBreakdownToEpoch(short year, short jDay, short month, short day, double hour, double *epochTime)
Converts a broken-down time into epoch time.
short TimeEpochToText(char *text, double epochTime)
Converts epoch time to a formatted text string.