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

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

Coupla bugfixes.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 10.3 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#define INCL_DOSMISC
44#include <os2.h>
45
46#include <stdio.h>
47
48#include "setup.h" // code generation and debugging options
49
50#include "helpers\datetime.h"
51
52#pragma hdrstop
53
54/*
55 *@@category: Helpers\C helpers\Date/time helpers
56 */
57
58/*******************************************************************
59 * *
60 * Private declarations *
61 * *
62 ******************************************************************/
63
64const char *pcszFormatTimestamp = "%4u%02u%02u%02u%02u%02u%";
65
66ULONG G_ulDateScalarFirstCalled = 0;
67
68/*
69 *@@ dtGetULongTime:
70 * this returns the current time as a ULONG value (in milliseconds).
71 * Useful for stopping how much time the machine has spent in
72 * a certain function. To do this, simply call this function twice,
73 * and subtract the two values, which will give you the execution
74 * time in milliseconds.
75 *
76 * A ULONG can hold a max value of 4'294'967'295.
77 * So this overflows after 49.71... days.
78 *
79 *@@V0.9.7 (2000-12-08) [umoeller]: replaced, now using DosQuerySysInfo(QSV_MS_COUNT)
80 */
81
82ULONG dtGetULongTime(VOID)
83{
84 ULONG ulTimeNow;
85 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
86 &ulTimeNow,
87 sizeof(ulTimeNow));
88 return (ulTimeNow);
89
90 /* DATETIME dt;
91 ULONG ulHours,
92 ulDaysPassed = 0;
93
94 if (G_ulDateScalarFirstCalled == 0)
95 {
96 // first call:
97 G_ulDateScalarFirstCalled = dtDate2Scalar(dt.year,
98 dt.month,
99 dt.day);
100 }
101 else
102 {
103 // not first call:
104 ULONG ulDateScalarNow = dtDate2Scalar(dt.year,
105 dt.month,
106 dt.day);
107 ulDaysPassed = (ulDateScalarNow - G_ulDateScalarFirstCalled);
108 _Pmpf((__FUNCTION__ ": days passed = %d", ulDaysPassed));
109 }
110
111 DosGetDateTime(&dt);
112 ulHours = dt.hours; // this is UCHAR in DATETIME
113 // get the hours; for every day passed, add 24 hours...
114 ulHours += (24 * ulDaysPassed);
115 // 0 if we're still on the first date
116
117 return (10*(dt.hundredths + 100*(dt.seconds + 60*(dt.minutes + 60*(ulHours))))); */
118}
119
120/*
121 *@@ dtCreateFileTimeStamp:
122 * this creates a time stamp string in pszTimeStamp
123 * from the given FDATE and FTIME structures (which
124 * are, for example, used in the FILESTATUS3 structure
125 * returned by DosQueryPathInfo).
126 *
127 * The time stamp string is exactly 15 bytes in length
128 * (including the terminating null byte) and has the
129 * following format:
130 + YYYYMMDDhhmmss
131 * (being year, mondth, day, hours, minutes, seconds).
132 * Your buffer must be large enough for that, this is
133 * not checked.
134 *
135 * This time stamp can be used to compare two dates
136 * simply by calling strcmp.
137 *
138 * Note that since FTIME only has a two-seconds resolution,
139 * the seconds part of the time stamp will have that too.
140 *
141 * This returns the string length (excluding the null
142 * terminator), which should be 14.
143 *
144 *@@added V0.9.0 [umoeller]
145 */
146
147int dtCreateFileTimeStamp(PSZ pszTimeStamp, // out: time stamp
148 FDATE* pfdate, // in: date
149 FTIME* pftime) // in: time
150{
151 return (sprintf(pszTimeStamp,
152 pcszFormatTimestamp,
153 pfdate->year + 1980,
154 pfdate->month,
155 pfdate->day,
156 pftime->hours,
157 pftime->minutes,
158 pftime->twosecs * 2));
159}
160
161/*
162 *@@ dtCreateDosTimeStamp:
163 * just like dtCreateFileTimeStamp,
164 * except that this takes a DATETIME
165 * structure as input. The time stamp
166 * string is exactly the same.
167 *
168 *@@added V0.9.0 [umoeller]
169 */
170
171int dtCreateDosTimeStamp(PSZ pszTimeStamp,
172 DATETIME* pdt)
173{
174 return (sprintf(pszTimeStamp,
175 pcszFormatTimestamp,
176 pdt->year,
177 pdt->month,
178 pdt->day,
179 pdt->hours,
180 pdt->minutes,
181 pdt->seconds));
182}
183
184/*
185**
186**
187** day: day of month
188** mon: month (1-12)
189** yr: year
190**
191**
192*/
193
194/*
195 *@@ dtDayOfWeek:
196 * returns an integer that represents the day of
197 * the week for the date passed as parameters.
198 *
199 * Returns 0-6 where 0 is sunday.
200 *
201 *@@added V0.9.7 (2000-12-05) [umoeller]
202 */
203
204ULONG dtDayOfWeek(ULONG day,
205 ULONG mon, // 1-12
206 ULONG yr)
207{
208 int dow;
209
210 if (mon <= 2)
211 {
212 mon += 12;
213 yr -= 1;
214 }
215 dow = ( day
216 + mon * 2
217 + ((mon + 1) * 6) / 10
218 + yr
219 + yr / 4
220 - yr / 100
221 + yr / 400
222 + 2);
223 dow = dow % 7;
224 return ((dow ? dow : 7) - 1);
225}
226
227/*
228 *@@ dtIsLeapYear:
229 * returns TRUE if yr is a leap year.
230 *
231 * (c) Ray Gardner.
232 */
233
234int dtIsLeapYear(unsigned yr)
235{
236 return ( (yr % 400 == 0)
237 || ( (yr % 4 == 0)
238 && (yr % 100 != 0)
239 )
240 );
241}
242
243/*
244 *@@ dtMonths2Days:
245 * returns the no. of days for the beginning
246 * of "month" (starting from 1).
247 *
248 * For example, if you pass 1 (for january),
249 * you get 0 because there's no days at jan 1st
250 * yet.
251 *
252 * If you pass 2 (for february), you get 31.
253 *
254 * If you pass 3 (for march), you get 61.
255 *
256 * This is useful for computing a day index
257 * for a given month/day pair. Pass the month
258 * in here and add (day-1); for march 3rd,
259 * you then get 63.
260 *
261 * (c) Ray Gardner.
262 */
263
264unsigned dtMonths2Days(unsigned month)
265{
266 return (month * 3057 - 3007) / 100;
267}
268
269/*
270 *@@ dtYears2Days:
271 * converts a year to the no. of days passed.
272 *
273 * (c) Ray Gardner.
274 */
275
276long dtYears2Days (unsigned yr)
277{
278 return ( yr * 365L
279 + yr / 4
280 - yr / 100
281 + yr / 400);
282}
283
284/*
285 *@@ dtDate2Scalar:
286 * returns a scalar (i.e. the no. of days) for
287 * the given date.
288 *
289 * (c) Ray Gardner.
290 */
291
292long dtDate2Scalar(unsigned yr, // in: year (e.g. 1999)
293 unsigned mo, // in: month (1-12)
294 unsigned day) // in: day (1-31)
295{
296 long scalar;
297 scalar = day + dtMonths2Days(mo);
298 if ( mo > 2 ) /* adjust if past February */
299 scalar -= dtIsLeapYear(yr) ? 1 : 2;
300 yr--;
301 scalar += dtYears2Days(yr);
302 return scalar;
303}
304
305/*
306 *@@ dtScalar2Date:
307 *
308 *
309 * (c) Ray Gardner.
310 */
311
312void dtScalar2Date(long scalar, // in: date scalar
313 unsigned *pyr, // out: year (e.g. 1999)
314 unsigned *pmo, // out: month (1-12)
315 unsigned *pday) // out: day (1-31)
316{
317 unsigned n; /* compute inverse of dtYears2Days() */
318
319 for ( n = (unsigned)((scalar * 400L) / 146097); dtYears2Days(n) < scalar;)
320 n++; /* 146097 == dtYears2Days(400) */
321 *pyr = n;
322 n = (unsigned)(scalar - dtYears2Days(n-1));
323 if ( n > 59 ) /* adjust if past February */
324 {
325 n += 2;
326 if ( dtIsLeapYear(*pyr) )
327 n -= n > 62 ? 1 : 2;
328 }
329 *pmo = (n * 100 + 3007) / 3057; /* inverse of dtMonths2Days() */
330 *pday = n - dtMonths2Days(*pmo);
331}
332
333/*
334 *@@ dtIsValidDate:
335 * returns TRUE if the given date is valid.
336 *
337 *@@added V0.9.7 (2000-12-05) [umoeller]
338 */
339
340BOOL dtIsValidDate(LONG day, // in: day (1-31)
341 LONG month, // in: month (1-12)
342 ULONG year) // in: year (e.g. 1999)
343{
344 BOOL brc = FALSE;
345 if (day > 0)
346 {
347 switch( month )
348 {
349 case 1 :
350 case 3 :
351 case 5 :
352 case 7 :
353 case 8 :
354 case 10 :
355 case 12 :
356 if (day <= 31)
357 brc = TRUE;
358 break;
359
360 case 4 :
361 case 6 :
362 case 9 :
363 case 11 :
364 if (day <= 30)
365 brc = TRUE;
366 break;
367
368 case 2 :
369 if (day < 29)
370 brc = TRUE;
371 else
372 if (day == 29)
373 if (dtIsLeapYear(year))
374 return 1 ;
375 }
376 }
377 return (brc);
378}
379
Note: See TracBrowser for help on using the repository browser.