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

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

Final changes for 0.9.7, i hope...

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