OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [g-calend.adb] - Blame information for rev 292

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT RUN-TIME COMPONENTS                         --
4
--                                                                          --
5
--                         G N A T . C A L E N D A R                        --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--                     Copyright (C) 1999-2009, AdaCore                     --
10
--                                                                          --
11
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
12
-- terms of the  GNU General Public License as published  by the Free Soft- --
13
-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
14
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17
-- for  more details.  You should have  received  a copy of the GNU General --
18
-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
19
-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
20
-- Boston, MA 02110-1301, USA.                                              --
21
--                                                                          --
22
-- As a special exception,  if other files  instantiate  generics from this --
23
-- unit, or you link  this unit with other files  to produce an executable, --
24
-- this  unit  does not  by itself cause  the resulting  executable  to  be --
25
-- covered  by the  GNU  General  Public  License.  This exception does not --
26
-- however invalidate  any other reasons why  the executable file  might be --
27
-- covered by the  GNU Public License.                                      --
28
--                                                                          --
29
-- GNAT was originally developed  by the GNAT team at  New York University. --
30
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
31
--                                                                          --
32
------------------------------------------------------------------------------
33
 
34
package body GNAT.Calendar is
35
 
36
   use Ada.Calendar;
37
   use Interfaces;
38
 
39
   -----------------
40
   -- Day_In_Year --
41
   -----------------
42
 
43
   function Day_In_Year (Date : Time) return Day_In_Year_Number is
44
      Year     : Year_Number;
45
      Month    : Month_Number;
46
      Day      : Day_Number;
47
      Day_Secs : Day_Duration;
48
      pragma Unreferenced (Day_Secs);
49
   begin
50
      Split (Date, Year, Month, Day, Day_Secs);
51
      return Julian_Day (Year, Month, Day) - Julian_Day (Year, 1, 1) + 1;
52
   end Day_In_Year;
53
 
54
   -----------------
55
   -- Day_Of_Week --
56
   -----------------
57
 
58
   function Day_Of_Week (Date : Time) return Day_Name is
59
      Year     : Year_Number;
60
      Month    : Month_Number;
61
      Day      : Day_Number;
62
      Day_Secs : Day_Duration;
63
      pragma Unreferenced (Day_Secs);
64
   begin
65
      Split (Date, Year, Month, Day, Day_Secs);
66
      return Day_Name'Val ((Julian_Day (Year, Month, Day)) mod 7);
67
   end Day_Of_Week;
68
 
69
   ----------
70
   -- Hour --
71
   ----------
72
 
73
   function Hour (Date : Time) return Hour_Number is
74
      Year       : Year_Number;
75
      Month      : Month_Number;
76
      Day        : Day_Number;
77
      Hour       : Hour_Number;
78
      Minute     : Minute_Number;
79
      Second     : Second_Number;
80
      Sub_Second : Second_Duration;
81
      pragma Unreferenced (Year, Month, Day, Minute, Second, Sub_Second);
82
   begin
83
      Split (Date, Year, Month, Day, Hour, Minute, Second, Sub_Second);
84
      return Hour;
85
   end Hour;
86
 
87
   ----------------
88
   -- Julian_Day --
89
   ----------------
90
 
91
   --  Julian_Day is used to by Day_Of_Week and Day_In_Year. Note that this
92
   --  implementation is not expensive.
93
 
94
   function Julian_Day
95
     (Year  : Year_Number;
96
      Month : Month_Number;
97
      Day   : Day_Number) return Integer
98
   is
99
      Internal_Year  : Integer;
100
      Internal_Month : Integer;
101
      Internal_Day   : Integer;
102
      Julian_Date    : Integer;
103
      C              : Integer;
104
      Ya             : Integer;
105
 
106
   begin
107
      Internal_Year  := Integer (Year);
108
      Internal_Month := Integer (Month);
109
      Internal_Day   := Integer (Day);
110
 
111
      if Internal_Month > 2 then
112
         Internal_Month := Internal_Month - 3;
113
      else
114
         Internal_Month := Internal_Month + 9;
115
         Internal_Year  := Internal_Year - 1;
116
      end if;
117
 
118
      C  := Internal_Year / 100;
119
      Ya := Internal_Year - (100 * C);
120
 
121
      Julian_Date := (146_097 * C) / 4 +
122
        (1_461 * Ya) / 4 +
123
        (153 * Internal_Month + 2) / 5 +
124
        Internal_Day + 1_721_119;
125
 
126
      return Julian_Date;
127
   end Julian_Day;
128
 
129
   ------------
130
   -- Minute --
131
   ------------
132
 
133
   function Minute (Date : Time) return Minute_Number is
134
      Year       : Year_Number;
135
      Month      : Month_Number;
136
      Day        : Day_Number;
137
      Hour       : Hour_Number;
138
      Minute     : Minute_Number;
139
      Second     : Second_Number;
140
      Sub_Second : Second_Duration;
141
      pragma Unreferenced (Year, Month, Day, Hour, Second, Sub_Second);
142
   begin
143
      Split (Date, Year, Month, Day, Hour, Minute, Second, Sub_Second);
144
      return Minute;
145
   end Minute;
146
 
147
   ------------
148
   -- Second --
149
   ------------
150
 
151
   function Second (Date : Time) return Second_Number is
152
      Year       : Year_Number;
153
      Month      : Month_Number;
154
      Day        : Day_Number;
155
      Hour       : Hour_Number;
156
      Minute     : Minute_Number;
157
      Second     : Second_Number;
158
      Sub_Second : Second_Duration;
159
      pragma Unreferenced (Year, Month, Day, Hour, Minute, Sub_Second);
160
   begin
161
      Split (Date, Year, Month, Day, Hour, Minute, Second, Sub_Second);
162
      return Second;
163
   end Second;
164
 
165
   -----------
166
   -- Split --
167
   -----------
168
 
169
   procedure Split
170
     (Date       : Time;
171
      Year       : out Year_Number;
172
      Month      : out Month_Number;
173
      Day        : out Day_Number;
174
      Hour       : out Hour_Number;
175
      Minute     : out Minute_Number;
176
      Second     : out Second_Number;
177
      Sub_Second : out Second_Duration)
178
   is
179
      Day_Secs : Day_Duration;
180
      Secs     : Natural;
181
 
182
   begin
183
      Split (Date, Year, Month, Day, Day_Secs);
184
 
185
      Secs       := (if Day_Secs = 0.0 then 0 else Natural (Day_Secs - 0.5));
186
      Sub_Second := Second_Duration (Day_Secs - Day_Duration (Secs));
187
      Hour       := Hour_Number (Secs / 3_600);
188
      Secs       := Secs mod 3_600;
189
      Minute     := Minute_Number (Secs / 60);
190
      Second     := Second_Number (Secs mod 60);
191
   end Split;
192
 
193
   ----------------
194
   -- Sub_Second --
195
   ----------------
196
 
197
   function Sub_Second (Date : Time) return Second_Duration is
198
      Year       : Year_Number;
199
      Month      : Month_Number;
200
      Day        : Day_Number;
201
      Hour       : Hour_Number;
202
      Minute     : Minute_Number;
203
      Second     : Second_Number;
204
      Sub_Second : Second_Duration;
205
      pragma Unreferenced (Year, Month, Day, Hour, Minute, Second);
206
   begin
207
      Split (Date, Year, Month, Day, Hour, Minute, Second, Sub_Second);
208
      return Sub_Second;
209
   end Sub_Second;
210
 
211
   -------------
212
   -- Time_Of --
213
   -------------
214
 
215
   function Time_Of
216
     (Year       : Year_Number;
217
      Month      : Month_Number;
218
      Day        : Day_Number;
219
      Hour       : Hour_Number;
220
      Minute     : Minute_Number;
221
      Second     : Second_Number;
222
      Sub_Second : Second_Duration := 0.0) return Time
223
   is
224
 
225
      Day_Secs : constant Day_Duration :=
226
                   Day_Duration (Hour   * 3_600) +
227
                   Day_Duration (Minute *    60) +
228
                   Day_Duration (Second)         +
229
                                 Sub_Second;
230
   begin
231
      return Time_Of (Year, Month, Day, Day_Secs);
232
   end Time_Of;
233
 
234
   -----------------
235
   -- To_Duration --
236
   -----------------
237
 
238
   function To_Duration (T : not null access timeval) return Duration is
239
 
240
      procedure timeval_to_duration
241
        (T    : not null access timeval;
242
         sec  : not null access C.long;
243
         usec : not null access C.long);
244
      pragma Import (C, timeval_to_duration, "__gnat_timeval_to_duration");
245
 
246
      Micro : constant := 10**6;
247
      sec   : aliased C.long;
248
      usec  : aliased C.long;
249
 
250
   begin
251
      timeval_to_duration (T, sec'Access, usec'Access);
252
      return Duration (sec) + Duration (usec) / Micro;
253
   end To_Duration;
254
 
255
   ----------------
256
   -- To_Timeval --
257
   ----------------
258
 
259
   function To_Timeval (D : Duration) return timeval is
260
 
261
      procedure duration_to_timeval
262
        (Sec  : C.long;
263
         Usec : C.long;
264
         T : not null access timeval);
265
      pragma Import (C, duration_to_timeval, "__gnat_duration_to_timeval");
266
 
267
      Micro  : constant := 10**6;
268
      Result : aliased timeval;
269
      sec    : C.long;
270
      usec   : C.long;
271
 
272
   begin
273
      if D = 0.0 then
274
         sec  := 0;
275
         usec := 0;
276
      else
277
         sec  := C.long (D - 0.5);
278
         usec := C.long ((D - Duration (sec)) * Micro - 0.5);
279
      end if;
280
 
281
      duration_to_timeval (sec, usec, Result'Access);
282
 
283
      return Result;
284
   end To_Timeval;
285
 
286
   ------------------
287
   -- Week_In_Year --
288
   ------------------
289
 
290
   function Week_In_Year (Date : Time) return Week_In_Year_Number is
291
      Year : Year_Number;
292
      Week : Week_In_Year_Number;
293
      pragma Unreferenced (Year);
294
   begin
295
      Year_Week_In_Year (Date, Year, Week);
296
      return Week;
297
   end Week_In_Year;
298
 
299
   -----------------------
300
   -- Year_Week_In_Year --
301
   -----------------------
302
 
303
   procedure Year_Week_In_Year
304
     (Date : Time;
305
      Year : out Year_Number;
306
      Week : out Week_In_Year_Number)
307
   is
308
      Month      : Month_Number;
309
      Day        : Day_Number;
310
      Hour       : Hour_Number;
311
      Minute     : Minute_Number;
312
      Second     : Second_Number;
313
      Sub_Second : Second_Duration;
314
      Jan_1      : Day_Name;
315
      Shift      : Week_In_Year_Number;
316
      Start_Week : Week_In_Year_Number;
317
 
318
      pragma Unreferenced (Hour, Minute, Second, Sub_Second);
319
 
320
      function Is_Leap (Year : Year_Number) return Boolean;
321
      --  Return True if Year denotes a leap year. Leap centennial years are
322
      --  properly handled.
323
 
324
      function Jan_1_Day_Of_Week
325
        (Jan_1     : Day_Name;
326
         Year      : Year_Number;
327
         Last_Year : Boolean := False;
328
         Next_Year : Boolean := False) return Day_Name;
329
      --  Given the weekday of January 1 in Year, determine the weekday on
330
      --  which January 1 fell last year or will fall next year as set by
331
      --  the two flags. This routine does not call Time_Of or Split.
332
 
333
      function Last_Year_Has_53_Weeks
334
        (Jan_1 : Day_Name;
335
         Year  : Year_Number) return Boolean;
336
      --  Given the weekday of January 1 in Year, determine whether last year
337
      --  has 53 weeks. A False value implies that the year has 52 weeks.
338
 
339
      -------------
340
      -- Is_Leap --
341
      -------------
342
 
343
      function Is_Leap (Year : Year_Number) return Boolean is
344
      begin
345
         if Year mod 400 = 0 then
346
            return True;
347
         elsif Year mod 100 = 0 then
348
            return False;
349
         else
350
            return Year mod 4 = 0;
351
         end if;
352
      end Is_Leap;
353
 
354
      -----------------------
355
      -- Jan_1_Day_Of_Week --
356
      -----------------------
357
 
358
      function Jan_1_Day_Of_Week
359
        (Jan_1     : Day_Name;
360
         Year      : Year_Number;
361
         Last_Year : Boolean := False;
362
         Next_Year : Boolean := False) return Day_Name
363
      is
364
         Shift : Integer := 0;
365
 
366
      begin
367
         if Last_Year then
368
            Shift := (if Is_Leap (Year - 1) then -2 else -1);
369
         elsif Next_Year then
370
            Shift := (if Is_Leap (Year) then 2 else 1);
371
         end if;
372
 
373
         return Day_Name'Val ((Day_Name'Pos (Jan_1) + Shift) mod 7);
374
      end Jan_1_Day_Of_Week;
375
 
376
      ----------------------------
377
      -- Last_Year_Has_53_Weeks --
378
      ----------------------------
379
 
380
      function Last_Year_Has_53_Weeks
381
        (Jan_1 : Day_Name;
382
         Year  : Year_Number) return Boolean
383
      is
384
         Last_Jan_1 : constant Day_Name :=
385
                        Jan_1_Day_Of_Week (Jan_1, Year, Last_Year => True);
386
 
387
      begin
388
         --  These two cases are illustrated in the table below
389
 
390
         return
391
           Last_Jan_1 = Thursday
392
             or else (Last_Jan_1 = Wednesday and then Is_Leap (Year - 1));
393
      end Last_Year_Has_53_Weeks;
394
 
395
   --  Start of processing for Week_In_Year
396
 
397
   begin
398
      Split (Date, Year, Month, Day, Hour, Minute, Second, Sub_Second);
399
 
400
      --  According to ISO 8601, the first week of year Y is the week that
401
      --  contains the first Thursday in year Y. The following table contains
402
      --  all possible combinations of years and weekdays along with examples.
403
 
404
      --    +-------+------+-------+---------+
405
      --    | Jan 1 | Leap | Weeks | Example |
406
      --    +-------+------+-------+---------+
407
      --    |  Mon  |  No  |  52   |  2007   |
408
      --    +-------+------+-------+---------+
409
      --    |  Mon  | Yes  |  52   |  1996   |
410
      --    +-------+------+-------+---------+
411
      --    |  Tue  |  No  |  52   |  2002   |
412
      --    +-------+------+-------+---------+
413
      --    |  Tue  | Yes  |  52   |  1980   |
414
      --    +-------+------+-------+---------+
415
      --    |  Wed  |  No  |  52   |  2003   |
416
      --    +-------+------#########---------+
417
      --    |  Wed  | Yes  #  53   #  1992   |
418
      --    +-------+------#-------#---------+
419
      --    |  Thu  |  No  #  53   #  1998   |
420
      --    +-------+------#-------#---------+
421
      --    |  Thu  | Yes  #  53   #  2004   |
422
      --    +-------+------#########---------+
423
      --    |  Fri  |  No  |  52   |  1999   |
424
      --    +-------+------+-------+---------+
425
      --    |  Fri  | Yes  |  52   |  1988   |
426
      --    +-------+------+-------+---------+
427
      --    |  Sat  |  No  |  52   |  1994   |
428
      --    +-------+------+-------+---------+
429
      --    |  Sat  | Yes  |  52   |  1972   |
430
      --    +-------+------+-------+---------+
431
      --    |  Sun  |  No  |  52   |  1995   |
432
      --    +-------+------+-------+---------+
433
      --    |  Sun  | Yes  |  52   |  1956   |
434
      --    +-------+------+-------+---------+
435
 
436
      --  A small optimization, the input date is January 1. Note that this
437
      --  is a key day since it determines the number of weeks and is used
438
      --  when special casing the first week of January and the last week of
439
      --  December.
440
 
441
      Jan_1 := Day_Of_Week (if Day = 1 and then Month = 1
442
                            then Date
443
                            else (Time_Of (Year, 1, 1, 0.0)));
444
 
445
      --  Special cases for January
446
 
447
      if Month = 1 then
448
 
449
         --  Special case 1: January 1, 2 and 3. These three days may belong
450
         --  to last year's last week which can be week number 52 or 53.
451
 
452
         --    +-----+-----+-----+=====+-----+-----+-----+
453
         --    | Mon | Tue | Wed # Thu # Fri | Sat | Sun |
454
         --    +-----+-----+-----+-----+-----+-----+-----+
455
         --    | 26  | 27  | 28  # 29  # 30  | 31  |  1  |
456
         --    +-----+-----+-----+-----+-----+-----+-----+
457
         --    | 27  | 28  | 29  # 30  # 31  |  1  |  2  |
458
         --    +-----+-----+-----+-----+-----+-----+-----+
459
         --    | 28  | 29  | 30  # 31  #  1  |  2  |  3  |
460
         --    +-----+-----+-----+=====+-----+-----+-----+
461
 
462
         if (Day = 1 and then Jan_1 in Friday .. Sunday)
463
               or else
464
            (Day = 2 and then Jan_1 in Friday .. Saturday)
465
               or else
466
            (Day = 3 and then Jan_1 = Friday)
467
         then
468
            Week := (if Last_Year_Has_53_Weeks (Jan_1, Year) then 53 else 52);
469
 
470
            --  January 1, 2 and 3 belong to the previous year
471
 
472
            Year := Year - 1;
473
            return;
474
 
475
         --  Special case 2: January 1, 2, 3, 4, 5, 6 and 7 of the first week
476
 
477
         --    +-----+-----+-----+=====+-----+-----+-----+
478
         --    | Mon | Tue | Wed # Thu # Fri | Sat | Sun |
479
         --    +-----+-----+-----+-----+-----+-----+-----+
480
         --    | 29  | 30  | 31  #  1  #  2  |  3  |  4  |
481
         --    +-----+-----+-----+-----+-----+-----+-----+
482
         --    | 30  | 31  |  1  #  2  #  3  |  4  |  5  |
483
         --    +-----+-----+-----+-----+-----+-----+-----+
484
         --    | 31  |  1  |  2  #  3  #  4  |  5  |  6  |
485
         --    +-----+-----+-----+-----+-----+-----+-----+
486
         --    |  1  |  2  |  3  #  4  #  5  |  6  |  7  |
487
         --    +-----+-----+-----+=====+-----+-----+-----+
488
 
489
         elsif (Day <= 4 and then Jan_1 in Monday .. Thursday)
490
                  or else
491
               (Day = 5  and then Jan_1 in Monday .. Wednesday)
492
                  or else
493
               (Day = 6  and then Jan_1 in Monday ..  Tuesday)
494
                  or else
495
               (Day = 7  and then Jan_1 = Monday)
496
         then
497
            Week := 1;
498
            return;
499
         end if;
500
 
501
      --  Month other than 1
502
 
503
      --  Special case 3: December 29, 30 and 31. These days may belong to
504
      --  next year's first week.
505
 
506
      --    +-----+-----+-----+=====+-----+-----+-----+
507
      --    | Mon | Tue | Wed # Thu # Fri | Sat | Sun |
508
      --    +-----+-----+-----+-----+-----+-----+-----+
509
      --    | 29  | 30  | 31  #  1  #  2  |  3  |  4  |
510
      --    +-----+-----+-----+-----+-----+-----+-----+
511
      --    | 30  | 31  |  1  #  2  #  3  |  4  |  5  |
512
      --    +-----+-----+-----+-----+-----+-----+-----+
513
      --    | 31  |  1  |  2  #  3  #  4  |  5  |  6  |
514
      --    +-----+-----+-----+=====+-----+-----+-----+
515
 
516
      elsif Month = 12 and then Day > 28 then
517
         declare
518
            Next_Jan_1 : constant Day_Name :=
519
                           Jan_1_Day_Of_Week (Jan_1, Year, Next_Year => True);
520
         begin
521
            if (Day = 29 and then Next_Jan_1 = Thursday)
522
                  or else
523
               (Day = 30 and then Next_Jan_1 in Wednesday .. Thursday)
524
                  or else
525
               (Day = 31 and then Next_Jan_1 in Tuesday .. Thursday)
526
            then
527
               Year := Year + 1;
528
               Week := 1;
529
               return;
530
            end if;
531
         end;
532
      end if;
533
 
534
      --  Determine the week from which to start counting. If January 1 does
535
      --  not belong to the first week of the input year, then the next week
536
      --  is the first week.
537
 
538
      Start_Week := (if Jan_1 in Friday .. Sunday then 1 else 2);
539
 
540
      --  At this point all special combinations have been accounted for and
541
      --  the proper start week has been found. Since January 1 may not fall
542
      --  on a Monday, shift 7 - Day_Name'Pos (Jan_1). This action ensures an
543
      --  origin which falls on Monday.
544
 
545
      Shift := 7 - Day_Name'Pos (Jan_1);
546
      Week  := Start_Week + (Day_In_Year (Date) - Shift - 1) / 7;
547
   end Year_Week_In_Year;
548
 
549
end GNAT.Calendar;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.