home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d128
/
mrbackup.lha
/
MRBackup
/
MRDates.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-01-02
|
10KB
|
422 lines
/* General routines to provide date support for the DateStamp
* date format.
*
* Author: Mark R. Rinfret (mark@unisec.usi.com)
* Date: 07/18/87
*
* This source is released to the public domain by the author, without
* restrictions. However, it is requested that you give credit where
* credit is due and share any bug fixes or enhancements with him.
*
* History: (most recent change first)
*
* 08/20/87 -MRR- Gack! I wrote this? In the interests of orthogonality,
* I have replaced SetDateStamp with PackDS, the inverse
* of UnpackDS. I have also renamed the package MRDates
* to provide a unique name, hopefully relieving conflicts
* with other packages providing date/time functions. The
* UnpackedDS type is now defined in MRDates.h and can
* be included by modules which require PackDS and UnpackDS.
*/
/* The following #define MUST be set to inhibit certain declarations in
* the include file MRDates.h:
*/
#define MRDATES
#include <libraries/dos.h>
#include <exec/memory.h>
#include <ctype.h>
#include <functions.h>
#include "MRDates.h"
/* #define DEBUG */
char *daynames[] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
};
USHORT monthdays[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
char *monthnames[12] = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
};
/* Compare two DateStamp values.
* Called with:
* d1,d2: pointers to DateStamp structs
*
* Returns:
* < 0 => d1 < d2
* 0 => d1 == d2
* > 0 => d1 > d2
*
* Note:
* This routine makes an assumption about the DateStamp structure,
* specifically that it can be viewed as an array of 3 long integers
* in days, minutes and ticks order.
*/
int
CompareDS(d1, d2)
long *d1, *d2;
{
USHORT i;
long compare;
for (i = 0; i < 3; ++i) {
if (compare = (d1[i] - d2[i])) {
if (compare < 0) return -1;
return 1;
}
}
return 0; /* dates match */
}
/* Convert a DateStamp to a formatted string.
* Called with:
* fmt: format string
* The format of the format string is very similar to that
* for printf, with the exception that the following letters
* have special significance:
* y => year minus 1900
* Y => full year value
* m => month value as integer
* M => month name
* d => day of month (1..31)
* D => day name ("Monday".."Sunday")
* h => hour in twenty-four hour notation
* H => hour in twelve hour notation
* i => 12 hour indicator for H notation (AM or PM)
* I => same as i
* n => minutes (sorry...conflict with m = months)
* N => same as n
* s => seconds
* S => same as s
*
* All other characters are passed through as part of the normal
* formatting process. The following are some examples with
* Saturday, July 18, 1987, 13:53 as an input date:
*
* "%y/%m/%d" => 87/7/18
* "%02m/%02d/%2y" => 07/18/87
* "%D, %M %d, %Y" => Saturday, July 18, 1987
* "%02H:%02m i" => 01:53 PM
* "Time now: %h%m" => Time now: 13:53
*
* str: string to write date on
* d: pointer to DateStamp structure
*
*/
void
DS2Str(str,fmt,d)
char *str, *fmt; struct DateStamp *d;
{
UnpackedDS date;
char fc,*fs,*out;
USHORT ivalue;
char new_fmt[256]; /* make it big to be "safe" */
USHORT new_fmt_lng;
char *svalue;
UnpackDS(d, &date); /* convert DateStamp to unpacked format */
*str = '\0'; /* insure output is empty */
out = str;
fs = fmt; /* make copy of format string pointer */
while (fc = *fs++) { /* get format characters */
if (fc == '%') { /* formatting meta-character? */
new_fmt_lng = 0;
new_fmt[new_fmt_lng++] = fc;
/* copy width information */
while (isdigit(fc = *fs++) || fc == '-')
new_fmt[new_fmt_lng++] = fc;
switch (fc) { /* what are we trying to do? */
case 'y': /* year - 1980 */
ivalue = date.year - 1900;
write_int:
new_fmt[new_fmt_lng++] = 'd';
new_fmt[new_fmt_lng] = '\0';
sprintf(out,new_fmt,ivalue);
out = str + strlen(str);
break;
case 'Y': /* full year value */
ivalue = date.year;
goto write_int;
case 'm': /* month */
ivalue = date.month;
goto write_int;
case 'M': /* month name */
svalue = monthnames[date.month - 1];
write_str:
new_fmt[new_fmt_lng++] = 's';
new_fmt[new_fmt_lng] = '\0';
sprintf(out,new_fmt,svalue);
out = str + strlen(str);
break;
case 'd': /* day */
ivalue = date.day;
goto write_int;
case 'D': /* day name */
svalue = daynames[d->ds_Days % 7];
goto write_str;
case 'h': /* hour */
ivalue = date.hour;
goto write_int;
case 'H': /* hour in 12 hour notation */
ivalue = date.hour;
if (ivalue >= 12) ivalue -= 12;
goto write_int;
case 'i': /* AM/PM indicator */
case 'I':
if (date.hour >= 12)
svalue = "PM";
else
svalue = "AM";
goto write_str;
case 'n': /* minutes */
case 'N':
ivalue = date.minute;
goto write_int;
case 's': /* seconds */
case 'S':
ivalue = date.second;
goto write_int;
default:
/* We are in deep caca - don't know what to do with this
* format character. Copy the raw format string to the
* output as debugging information.
*/
new_fmt[new_fmt_lng++] = fc;
new_fmt[new_fmt_lng] = '\0';
strcat(out, new_fmt);
out = out + strlen(out); /* advance string pointer */
break;
}
}
else
*out++ = fc; /* copy literal character */
}
*out = '\0'; /* terminating null */
}
/* Convert a string to a DateStamp.
* Called with:
* str: string containing date in MM/DD/YY format
* d: pointer to DateStamp structure
* Returns:
* status code (0 => success, 1 => failure)
*/
int
Str2DS(str, d)
char *str; struct DateStamp *d;
{
register char c;
int count;
int i, item;
UnpackedDS upd; /* unpacked DateStamp */
char *s;
int values[3];
int value;
s = str;
for (item = 0; item < 2; ++item) { /* item = date, then time */
for (i = 0; i < 3; ++i) values[i] = 0;
count = 0;
while (c = *s++) { /* get date value */
if (c <= ' ')
break;
if (isdigit(c)) {
value = 0;
do {
value = value*10 + c - '0';
c = *s++;
} while (isdigit(c));
if (count == 3) {
bad_value:
#ifdef DEBUG
puts("Error in date-time format.\n");
printf("at %s: values(%d) = %d, %d, %d\n",
s, count, values[0], values[1], values[2]);
#endif
return 1;
}
values[count++] = value;
if (c <= ' ')
break;
}
} /* end while */
if (item) { /* getting time? */
upd.hour = values[0];
upd.minute = values[1];
upd.second = values[2];
}
else { /* getting date? */
/* It's OK to have a null date string, but it's not OK to specify only
* 1 or 2 of the date components.
*/
if (count && count != 3)
goto bad_value;
upd.month = values[0];
upd.day = values[1];
upd.year = values[2];
}
} /* end for */
PackDS(d,&upd);
return 0;
}
/* Set a DateStamp structure, given the date/time components.
* Called with:
* d: pointer to DateStamp
* upd: pointer to UnpackedDS
*/
PackDS(d,upd)
struct DateStamp *d; UnpackedDS *upd;
{
USHORT leapyear;
short year,month,day,hour,minute,second;
year = upd->year; /* copy date components to locals */
month = upd->month;
day = upd->day;
hour = upd->hour;
minute = upd->minute;
second = upd->second;
if (year > 1900)
year = year - 1900;
leapyear = (year % 4 ? 0 : 1);
year = year - 78;
if (month < 1 || month > 12) /* somebody goofed? */
month = 1;
day = day - 1 + monthdays[month-1];
if (leapyear && (month > 2))
++day;
d->ds_Days = year * 365 + (year + 1) / 4 + day;
d->ds_Minute = hour * 60 + minute;
d->ds_Tick = second * TICKS_PER_SECOND;
}
/* Unpack a DateStamp structure into an UnpackedDS structure.
* Called with:
* ds: pointer to DateStamp structure
* du: pointer to UnpackedDS structure
*/
UnpackDS(ds, du)
struct DateStamp *ds; UnpackedDS *du;
{
USHORT i, leap_years, leap, temp, test_value;
du->year = ds->ds_Days / 365 + 1978;
/* is current year a leapyear? */
leap = ( (du->year % 4) == 0);
/* how many leap years since "beginning of time"? */
leap_years = (du->year - 1976 - 1) / 4;
/* get days remaining in year */
temp = ds->ds_Days % 365 - leap_years;
/* find month */
du->month = 0;
du->day = 0;
for (i = 11; i >= 0; --i) {
test_value = monthdays[i];
if (i > 2) test_value += leap;
if (temp >= test_value) {
du->month = i + 1;
du->day = temp - test_value + 1;
break;
}
}
du->hour = ds->ds_Minute / 60;
du->minute = ds->ds_Minute % 60;
du->second = ds->ds_Tick / TICKS_PER_SECOND;
}
#ifdef DEBUG
main()
{
int compflag;
char datestr[81], instr[81];
struct DateStamp *ds, *now;
UnpackedDS du;
now = (struct DateStamp *)
AllocMem((long) sizeof(struct DateStamp), MEMF_PUBLIC);
ds = (struct DateStamp *)
AllocMem((long) sizeof(struct DateStamp), MEMF_PUBLIC);
puts("Enter a date string and I will convert it. To quit, hit RETURN");
while (1) {
DateStamp(now);
UnpackDS(now, &du);
printf("\nCurrent date and time: %02d/%02d/%02d %02d:%02d:%02d\n",
du.month,du.day,du.year,du.hour,du.minute,du.second);
puts("\nEnter the date [and time]:");
gets(instr);
if (*instr == '\0') break;
if (Str2DS(instr,ds))
puts("Error encountered in input string");
else {
DS2Str(datestr, "%02m/%02d/%02y %02h:%02n:%02s", ds);
puts(datestr);
DS2Str(datestr, "%D, %M %d, %Y", ds);
puts(datestr);
DS2Str(datestr, "The time entered is %02H:%02N %i", ds);
puts(datestr);
compflag = CompareDS(ds,now);
printf("The date input is ");
if (compflag < 0)
printf("earlier than");
else if (compflag == 0)
printf("the same as");
else
printf("later than");
puts(" the current date.");
}
}
FreeMem(ds, (long) sizeof(struct DateStamp));
FreeMem(now, (long) sizeof(struct DateStamp));
}
#endif