dcf_2.0.2_9ba2652f/src/dcf-streams-calendar.adb

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
package body DCF.Streams.Calendar is

   procedure Set_Time (S : out Root_Zipstream_Type'Class; Modification_Time : Ada.Calendar.Time) is
   begin
      Set_Time (S, Calendar.Convert (Modification_Time));
   end Set_Time;

   function Get_Time (S : in Root_Zipstream_Type'Class) return Ada.Calendar.Time is
   begin
      return Calendar.Convert (Get_Time (S));
   end Get_Time;

   ------------------------------------------------
   --  Time = DOS Time. Valid through Year 2107  --
   ------------------------------------------------

   procedure Split
     (Date    :     Time;
      Year    : out Year_Number;
      Month   : out Month_Number;
      Day     : out Day_Number;
      Seconds : out Day_Duration)
   is
      D_Date       : constant Integer := Integer (Date / 65536);
      D_Time       : constant Integer := Integer (Date and 65535);
      X            : Integer;
      Hours        : Integer;
      Minutes      : Integer;
      Seconds_Only : Integer;
   begin
      Year := 1980 + D_Date / 512;
      X    := (D_Date / 32) mod 16;
      if X not in Month_Number then -- that is 0, or in 13..15
         raise Time_Error;
      end if;
      Month := X;
      X     := D_Date mod 32;
      if X not in Day_Number then -- that is 0
         raise Time_Error;
      end if;
      Day          := X;
      Hours        := D_Time / 2048;
      Minutes      := (D_Time / 32) mod 64;
      Seconds_Only := 2 * (D_Time mod 32);
      if Hours not in 0 .. 23 or Minutes not in 0 .. 59 or Seconds_Only not in 0 .. 59 then
         raise Time_Error;
      end if;
      Seconds := Day_Duration (Hours * 3600 + Minutes * 60 + Seconds_Only);
   end Split;

   function Time_Of
     (Year    : Year_Number;
      Month   : Month_Number;
      Day     : Day_Number;
      Seconds : Day_Duration := 0.0) return Time
   is
      Year_2       : Integer := Year;
      Hours        : Unsigned_32;
      Minutes      : Unsigned_32;
      Seconds_Only : Unsigned_32;
      Seconds_Day  : Unsigned_32;
      Result       : Unsigned_32;
   begin
      if Year_2 < 1980 then  --  Avoid invalid DOS date
         Year_2 := 1980;
      end if;
      Seconds_Day  := Unsigned_32 (Seconds);
      Hours        := Seconds_Day / 3600;
      Minutes      := (Seconds_Day / 60) mod 60;
      Seconds_Only := Seconds_Day mod 60;
      Result       :=
        --  MSDN formula for encoding:
        Unsigned_32 ((Year_2 - 1980) * 512 + Month * 32 + Day) * 65536  --  Date
        +
        Hours * 2048 +
        Minutes * 32 +
        Seconds_Only / 2; -- Time
      return Time (Result);
   end Time_Of;

   function ">" (Left, Right : Time) return Boolean is
   begin
      return Unsigned_32 (Left) > Unsigned_32 (Right);
   end ">";

   function Convert (Date : in Ada.Calendar.Time) return Time is
      Year            : Year_Number;
      Month           : Month_Number;
      Day             : Day_Number;
      Seconds_Day_Dur : Day_Duration;
   begin
      Split (Date, Year, Month, Day, Seconds_Day_Dur);
      return Time_Of (Year, Month, Day, Seconds_Day_Dur);
   end Convert;

   function Convert (Date : in Time) return Ada.Calendar.Time is
      Year            : Year_Number;
      Month           : Month_Number;
      Day             : Day_Number;
      Seconds_Day_Dur : Day_Duration;
   begin
      Split (Date, Year, Month, Day, Seconds_Day_Dur);
      return Time_Of (Year, Month, Day, Seconds_Day_Dur);
   end Convert;

end DCF.Streams.Calendar;