bump version
[AROS.git] / rom / utility / amiga2date.c
blobab6451a826ee54c8329e0415b1756f6236e1ec2e
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Convert the date from machine to human form.
6 Lang: english
7 */
8 #include "intern.h"
10 #if 1
11 const ULONG Utility_DayTable[]=
13 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335
15 #endif
17 /*****************************************************************************
19 NAME */
20 #include <utility/date.h>
21 #include <proto/utility.h>
23 AROS_LH2(void, Amiga2Date,
25 /* SYNOPSIS */
26 AROS_LHA(ULONG , seconds, D0),
27 AROS_LHA(struct ClockData *, result, A0),
29 /* LOCATION */
30 struct Library *, UtilityBase, 20, Utility)
32 /* FUNCTION
33 Convert the time value given as the number of seconds since the
34 1st of January 1978 (00:00:00 1.1.78), to a more useful values,
35 which is easier for most people to understand. These values will
36 be stored in the ClockData structure whose address is passed as
37 an argument.
39 INPUTS
40 seconds - Number of seconds since 1.1.78 00:00:00
41 result - The ClockData structure to store the information
42 in.
44 RESULT
45 The ClockData structure will contain the converted time values.
47 NOTES
49 EXAMPLE
51 BUGS
53 SEE ALSO
55 INTERNALS
56 Some information about some constants I use:
58 731 = 365 + 366, the number of days between 1.1.1978 and
59 1.1.1976. Using 1976 makes working out leap years
60 simpler.
61 1461 = The number of days in four years including 1 leap year.
62 (eg 365*3 + 366)
63 86400 = The number of seconds in one day.
65 I used these as constants so that they don't have to be computed
66 on the fly, or read from variables.
68 HISTORY
69 29-10-95 digulla automatically created from
70 utility_lib.fd and clib/utility_protos.h
71 19-05-96 iaint Wrote, with a little help from a Perl package.
72 11-08-96 iaint Updated for the new AROS format.
73 17-08-96 iaint Removed calls to unimplemented UDivMod32/UMult32
74 24-02-97 iaint Reimplemented, actually works now :)
76 *****************************************************************************/
78 AROS_LIBFUNC_INIT
80 #if 0
81 static const ULONG dim[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
82 #endif
83 LONG days;
84 LONG leap, year, month;
85 #if 0
86 LONG temp;
87 #endif
88 days = seconds / 86400;
89 result->wday = days % 7;
91 result->sec = seconds % 60;
92 seconds /= 60;
93 result->min = seconds % 60;
94 seconds /= 60;
95 result->hour = seconds % 24;
97 #if 1
98 /* stegerg: based on dos.library/datetostr */
100 leap = 1;
102 if(days<92*365+30*366)
105 1976 was a leap year so use it as a base to divide the days
106 into 4-year blocks (each beginning with a leap year).
108 days+=366+365;
109 year=4*(days/(366+3*365))+1976;
110 days%=(366+3*365);
112 /* Now divide the 4-year blocks into single years. */
113 if (days>=366)
115 leap=0;
116 days--;
117 year+=days/365;
118 days%=365;
121 else
124 The rule for calendar calculations are:
125 1. Every year even divisible by 4 is a leap year.
126 2. As an exception from rule 1 every year even divisible by
127 100 is not.
128 3. Every year even divisible by 400 is a leap year as an
129 exception from rule 2.
130 So 1996, 2000 and 2004 are leap years - 1900 and 1999 are not.
132 Use 2000 as a base to devide the days into 400 year blocks,
133 those into 100 year blocks and so on...
135 days-=17*365+5*366;
136 year=400*(days/(97*366+303*365))+2000;
137 days%=(97*366+303*365);
139 if(days>=366)
141 leap=0;
142 days--;
143 year+=100*(days/(24*366+76*365));
144 days%=(24*366+76*365);
146 if(days>=365)
148 leap=1;
149 days++;
150 year+=4*(days/(366+3*365));
151 days%=(366+3*365);
153 if(days>=366)
155 leap=0;
156 days--;
157 year+=days/365;
158 days%=365;
164 The starting-day table assumes a leap year - so add one day if
165 the date is after february 28th and the year is no leap year.
167 if(!leap&&days>=31+28)
168 days++;
170 for(month=11;;month--)
172 if(days>=Utility_DayTable[month])
174 days-=Utility_DayTable[month];
175 break;
179 /* Remember that 0 means 1.1.1978. */
180 days++;
181 month++;
183 result->month = month;
184 result->mday = days;
185 result->year = year;
187 #else
189 /* Calculate the current year.
191 Firstly, if the year is less than 1980, then the leap year
192 handling is not required...
195 if(days < 1096)
197 result->year = 1978;
199 if(days > 729)
200 leap = TRUE;
201 else
202 leap = FALSE;
204 year = (days / 365);
205 days = days - (year * 365);
207 else
210 We need to get into a year that follows a leap year, there
211 are two cases, >2100 and <=2100
213 If the year is after 2100, which is not a leap year, then
214 start point is 2101.
216 The first day in year 2101 is ...
218 if(days > 44925)
220 days -= 44926;
221 result->year = 2101;
224 Otherwise, we just set everything up so that we are relative
225 to 1981.
227 else
229 result->year = 1981;
230 days -= 1096;
234 From here, we know that every remaining set of 4 years
235 has 1 leap year...
237 year = days / 1461;
238 days -= year * 1461;
239 result->year += year * 4;
241 if(days > 1095)
242 leap = TRUE;
243 else
244 leap = FALSE;
246 year = days / 365;
247 days -= year * 365;
249 /* Now days is the number of days in the current year... */
250 } /* (not less than 1981) */
252 /* days now contains the days since the beginning of the current year */
253 for(temp = 0; (temp == 1) ? (days >= 28 + leap) : (days >= dim[temp]); temp++)
254 days -= (temp == 1) ? (28 + leap) : dim[temp];
256 result->month = temp + 1;
257 result->mday = days + 1;
258 result->year += year;
259 #endif
261 AROS_LIBFUNC_EXIT
263 } /* Amiga2Date */