source: trunk/src/helpers/datetime.c@ 14

Last change on this file since 14 was 14, checked in by umoeller, 25 years ago

Major updates; timers, LVM, miscellaneous.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 10.5 KB
Line 
1
2/*
3 *@@sourcefile datetime.c:
4 * contains various date and time helper functions.
5 * Some functions in here are OS/2-specific, others
6 * are plain C code.
7 *
8 * Functions marked with (C) Ray Gardner are from
9 * "scaldate.c":
10 * scalar date routines -- public domain by Ray Gardner
11 * These will work over the range 1/01/01 thru 14699/12/31
12 *
13 * Usage: All OS/2 programs.
14 *
15 * Function prefixes (new with V0.81):
16 * -- dat* date/time helper functions
17 *
18 * Note: Version numbering in this file relates to XWorkplace version
19 * numbering.
20 *
21 *@@header "helpers\datetime.h"
22 *@@added V0.9.0 [umoeller]
23 */
24
25/*
26 * This file Copyright (C) 1997-2000 Ulrich M”ller.
27 * This file is part of the "XWorkplace helpers" source package.
28 * This is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published
30 * by the Free Software Foundation, in version 2 as it comes in the
31 * "COPYING" file of the XWorkplace main distribution.
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 */
37
38#define OS2EMX_PLAIN_CHAR
39 // this is needed for "os2emx.h"; if this is defined,
40 // emx will define PSZ as _signed_ char, otherwise
41 // as unsigned char
42
43#include <os2.h>
44
45#include <stdio.h>
46
47#include "setup.h" // code generation and debugging options
48
49#include "helpers\datetime.h"
50
51#pragma hdrstop
52
53/*
54 *@@category: Helpers\C helpers\Date/time helpers
55 */
56
57/*******************************************************************
58 * *
59 * Private declarations *
60 * *
61 ******************************************************************/
62
63const char *pcszFormatTimestamp = "%4u%02u%02u%02u%02u%02u%";
64
65ULONG G_ulDateScalarFirstCalled = 0;
66
67/*
68 *@@ dtGetULongTime:
69 * this returns the current time as a ULONG value (in milliseconds).
70 * Useful for stopping how much time the machine has spent in
71 * a certain function. To do this, simply call this function twice,
72 * and subtract the two values, which will give you the execution
73 * time in milliseconds.
74 *
75 * Even though this does handle date information (i.e.
76 * will still return an increasing number when the
77 * clock switches from 23:59:59:9999 to 0:00:00:0000),
78 * this will not work forver after the first call.
79 * Here's the calculation:
80 *
81 + 1000 ms per second
82 + * 60 secs per minute
83 + * 60 minutes per hour
84 + * 24 hours per day
85 + = 86'400'000 after 23:59:59:9999
86 *
87 * A ULONG can hold a max value of 4'294'967'295.
88 * So this overflows after 49.71... days.
89 *
90 *@@changed V0.9.7 (2000-12-05) [umoeller]: now handling date also
91 */
92
93ULONG dtGetULongTime(VOID)
94{
95 DATETIME dt;
96 ULONG ulTime,
97 ulDateScalarPassed = 1;
98 DosGetDateTime(&dt);
99 ulTime = (10*(dt.hundredths + 100*(dt.seconds + 60*(dt.minutes + 60*(dt.hours)))));
100
101 if (G_ulDateScalarFirstCalled == 0)
102 {
103 // first call:
104 G_ulDateScalarFirstCalled = dtDate2Scalar(dt.year,
105 dt.month,
106 dt.day);
107 }
108 else
109 {
110 // not first call:
111 ULONG ulDateScalarNow = dtDate2Scalar(dt.year,
112 dt.month,
113 dt.day);
114 // calculate days passed since first call;
115 // this should be 1 if the date hasn't changed
116 ulDateScalarPassed = (G_ulDateScalarFirstCalled - ulDateScalarNow) + 1;
117 }
118
119 return (ulTime * ulDateScalarPassed);
120}
121
122/*
123 *@@ dtCreateFileTimeStamp:
124 * this creates a time stamp string in pszTimeStamp
125 * from the given FDATE and FTIME structures (which
126 * are, for example, used in the FILESTATUS3 structure
127 * returned by DosQueryPathInfo).
128 *
129 * The time stamp string is exactly 15 bytes in length
130 * (including the terminating null byte) and has the
131 * following format:
132 + YYYYMMDDhhmmss
133 * (being year, mondth, day, hours, minutes, seconds).
134 * Your buffer must be large enough for that, this is
135 * not checked.
136 *
137 * This time stamp can be used to compare two dates
138 * simply by calling strcmp.
139 *
140 * Note that since FTIME only has a two-seconds resolution,
141 * the seconds part of the time stamp will have that too.
142 *
143 * This returns the string length (excluding the null
144 * terminator), which should be 14.
145 *
146 *@@added V0.9.0 [umoeller]
147 */
148
149int dtCreateFileTimeStamp(PSZ pszTimeStamp, // out: time stamp
150 FDATE* pfdate, // in: date
151 FTIME* pftime) // in: time
152{
153 return (sprintf(pszTimeStamp,
154 pcszFormatTimestamp,
155 pfdate->year + 1980,
156 pfdate->month,
157 pfdate->day,
158 pftime->hours,
159 pftime->minutes,
160 pftime->twosecs * 2));
161}
162
163/*
164 *@@ dtCreateDosTimeStamp:
165 * just like dtCreateFileTimeStamp,
166 * except that this takes a DATETIME
167 * structure as input. The time stamp
168 * string is exactly the same.
169 *
170 *@@added V0.9.0 [umoeller]
171 */
172
173int dtCreateDosTimeStamp(PSZ pszTimeStamp,
174 DATETIME* pdt)
175{
176 return (sprintf(pszTimeStamp,
177 pcszFormatTimestamp,
178 pdt->year,
179 pdt->month,
180 pdt->day,
181 pdt->hours,
182 pdt->minutes,
183 pdt->seconds));
184}
185
186/*
187**
188**
189** day: day of month
190** mon: month (1-12)
191** yr: year
192**
193**
194*/
195
196/*
197 *@@ dtDayOfWeek:
198 * returns an integer that represents the day of
199 * the week for the date passed as parameters.
200 *
201 * Returns 0-6 where 0 is sunday.
202 *
203 *@@added V0.9.7 (2000-12-05) [umoeller]
204 */
205
206ULONG dtDayOfWeek(ULONG day,
207 ULONG mon, // 1-12
208 ULONG yr)
209{
210 int dow;
211
212 if (mon <= 2)
213 {
214 mon += 12;
215 yr -= 1;
216 }
217 dow = ( day
218 + mon * 2
219 + ((mon + 1) * 6) / 10
220 + yr
221 + yr / 4
222 - yr / 100
223 + yr / 400
224 + 2);
225 dow = dow % 7;
226 return ((dow ? dow : 7) - 1);
227}
228
229/*
230 *@@ dtIsLeapYear:
231 * returns TRUE if yr is a leap year.
232 *
233 * (c) Ray Gardner.
234 */
235
236int dtIsLeapYear(unsigned yr)
237{
238 return ( (yr % 400 == 0)
239 || ( (yr % 4 == 0)
240 && (yr % 100 != 0)
241 )
242 );
243}
244
245/*
246 *@@ dtMonths2Days:
247 * returns the no. of days for the beginning
248 * of "month" (starting from 1).
249 *
250 * For example, if you pass 1 (for january),
251 * you get 0 because there's no days at jan 1st
252 * yet.
253 *
254 * If you pass 2 (for february), you get 31.
255 *
256 * If you pass 3 (for march), you get 61.
257 *
258 * This is useful for computing a day index
259 * for a given month/day pair. Pass the month
260 * in here and add (day-1); for march 3rd,
261 * you then get 63.
262 *
263 * (c) Ray Gardner.
264 */
265
266unsigned dtMonths2Days(unsigned month)
267{
268 return (month * 3057 - 3007) / 100;
269}
270
271/*
272 *@@ dtYears2Days:
273 * converts a year to the no. of days passed.
274 *
275 * (c) Ray Gardner.
276 */
277
278long dtYears2Days (unsigned yr)
279{
280 return ( yr * 365L
281 + yr / 4
282 - yr / 100
283 + yr / 400);
284}
285
286/*
287 *@@ dtDate2Scalar:
288 * returns a scalar (i.e. the no. of days) for
289 * the given date.
290 *
291 * (c) Ray Gardner.
292 */
293
294long dtDate2Scalar(unsigned yr, // in: year (e.g. 1999)
295 unsigned mo, // in: month (1-12)
296 unsigned day) // in: day (1-31)
297{
298 long scalar;
299 scalar = day + dtMonths2Days(mo);
300 if ( mo > 2 ) /* adjust if past February */
301 scalar -= dtIsLeapYear(yr) ? 1 : 2;
302 yr--;
303 scalar += dtYears2Days(yr);
304 return scalar;
305}
306
307/*
308 *@@ dtScalar2Date:
309 *
310 *
311 * (c) Ray Gardner.
312 */
313
314void dtScalar2Date(long scalar, // in: date scalar
315 unsigned *pyr, // out: year (e.g. 1999)
316 unsigned *pmo, // out: month (1-12)
317 unsigned *pday) // out: day (1-31)
318{
319 unsigned n; /* compute inverse of dtYears2Days() */
320
321 for ( n = (unsigned)((scalar * 400L) / 146097); dtYears2Days(n) < scalar;)
322 n++; /* 146097 == dtYears2Days(400) */
323 *pyr = n;
324 n = (unsigned)(scalar - dtYears2Days(n-1));
325 if ( n > 59 ) /* adjust if past February */
326 {
327 n += 2;
328 if ( dtIsLeapYear(*pyr) )
329 n -= n > 62 ? 1 : 2;
330 }
331 *pmo = (n * 100 + 3007) / 3057; /* inverse of dtMonths2Days() */
332 *pday = n - dtMonths2Days(*pmo);
333}
334
335/*
336 *@@ dtIsValidDate:
337 * returns TRUE if the given date is valid.
338 *
339 *@@added V0.9.7 (2000-12-05) [umoeller]
340 */
341
342BOOL dtIsValidDate(LONG day, // in: day (1-31)
343 LONG month, // in: month (1-12)
344 ULONG year) // in: year (e.g. 1999)
345{
346 BOOL brc = FALSE;
347 if (day > 0)
348 {
349 switch( month )
350 {
351 case 1 :
352 case 3 :
353 case 5 :
354 case 7 :
355 case 8 :
356 case 10 :
357 case 12 :
358 if (day <= 31)
359 brc = TRUE;
360 break;
361
362 case 4 :
363 case 6 :
364 case 9 :
365 case 11 :
366 if (day <= 30)
367 brc = TRUE;
368 break;
369
370 case 2 :
371 if (day < 29)
372 brc = TRUE;
373 else
374 if (day == 29)
375 if (dtIsLeapYear(year))
376 return 1 ;
377 }
378 }
379 return (brc);
380}
381
Note: See TracBrowser for help on using the repository browser.