source: branches/branch-1-0/src/helpers/datetime.c@ 231

Last change on this file since 231 was 184, checked in by umoeller, 23 years ago

Second round of fixes for 0.9.19.

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