File: cpdfstrftime.ml

package info (click to toggle)
cpdf 2.8.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,828 kB
  • sloc: ml: 34,724; makefile: 65; sh: 45
file content (217 lines) | stat: -rw-r--r-- 6,438 bytes parent folder | download
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
(* C-Style strftime *)
open Pdfutil

type t =
  {_tm_sec : int;
   _tm_min : int;
   _tm_hour : int;
   _tm_mday : int;
   _tm_mon : int;
   _tm_year : int;
   _tm_wday : int;
   _tm_yday : int;
   _tm_isdst : bool}

let dummy =
  {_tm_sec = 0;
   _tm_min = 0;
   _tm_hour = 0;
   _tm_mday = 1;
   _tm_mon = 0;
   _tm_year = 2000;
   _tm_wday = 0;
   _tm_yday = 0;
   _tm_isdst = false}

let strf_A t =
  match t._tm_wday with
  | 0 -> "Sunday" | 1 -> "Monday" | 2 -> "Tuesday"
  | 3 -> "Wednesday" | 4 -> "Thursday" | 5 -> "Friday"
  | 6 -> "Saturday"
  | _ -> "strf_AFail"

let strf_a t =
  String.sub (strf_A t) 0 3

let strf_B t =
  match t._tm_mon with
  | 0 -> "January" | 1 -> "February" | 2 -> "March" | 3 -> "April"
  | 4 -> "May" | 5 -> "June" | 6 -> "July" | 7 -> "August"
  | 8 -> "September" | 9 -> "October" | 10 -> "November"
  | 11 -> "December" | _ -> "strf_Bfail"

let strf_b t =
  String.sub (strf_B t) 0 3

let strf_d t =
  let s = string_of_int t._tm_mday in 
    if String.length s = 1 then "0" ^ s else s

let strf_e t =
  let s = string_of_int t._tm_mday in
    if String.length s = 1 then " " ^ s else s

let strf_H t =
  let s = string_of_int t._tm_hour in
    if String.length s = 1 then "0" ^ s else s

let strf_I t =
  let s = string_of_int (t._tm_hour mod 12) in
    if String.length s = 1 then "0" ^ s else s

let strf_j t =
  let s = string_of_int t._tm_yday in
    match String.length s with
    | 1 -> "00" ^ s
    | 2 -> "0" ^ s
    | _ -> s

let strf_m t =
  let s = string_of_int (t._tm_mon + 1) in
    if String.length s = 1 then "0" ^ s else s

let strf_M t =
  let s = string_of_int t._tm_min in
    if String.length s = 1 then "0" ^ s else s

let strf_p t =
  if t._tm_hour >= 12 then "p.m" else "a.m"

let strf_S t =
  let s = string_of_int t._tm_sec in
    if String.length s = 1 then "0" ^ s else s

let strf_T t =
  strf_H t ^ ":" ^ strf_M t ^ ":" ^ strf_S t

let strf_u t =
  match t._tm_wday with
  | 0 -> "7"
  | n -> string_of_int (n + 1)

let strf_w t =
  string_of_int t._tm_wday

let strf_Y t =
  string_of_int (t._tm_year + 1900)

let strf_percent _ = "%"

let strftime_pairs =
  ["%a", strf_a; "%A", strf_A; "%b", strf_b; "%B", strf_B;
   "%d", strf_d; "%e", strf_e; "%H", strf_H;
   "%I", strf_I; "%j", strf_j; "%m", strf_m; "%M", strf_M;
   "%p", strf_p; "%S", strf_S; "%T", strf_T; "%u", strf_u;
   "%w", strf_w; "%Y", strf_Y; "%%", strf_percent]

let contents_of_file filename =
  let ch = open_in_bin filename in
  let s = really_input_string ch (in_channel_length ch) in
    close_in ch;
    s

(* Platform-independent current time and date with no Unix module *)
let utf8_of_utf16le s =
  implode (drop_evens (tl (tl (explode s))))

let year_day d m y =
  let n1 = 275 * m / 9 in
  let n2 = (m + 9) / 12 in
  let n3 = 1 + (y - 4 * (y / 4) + 2) / 3 in
    n1 - n2 * n3 + d - 30

(* OCAML *)
let js_date () = dummy

(* JS *)
(*
let js_date () =
  let d = Unix.localtime (Unix.time ()) in
  {_tm_sec = d.tm_sec;
   _tm_min = d.tm_min;
   _tm_hour = d.tm_hour;
   _tm_mday = d.tm_mday;
   _tm_mon = d.tm_mon;
   _tm_year = d.tm_year;
   _tm_wday = d.tm_wday;
   _tm_yday = d.tm_yday;
   _tm_isdst = d.tm_isdst}
*)

let return_date () =
  match Sys.backend_type with Sys.Other "js_of_ocaml" -> js_date () | _ ->
  match Sys.os_type with
    "Unix" ->
      (* Call the POSIX 'date' program, redirected to a temp file, and parse. *)
      let tempfile = Filename.temp_file "cpdf" "strftime" in
      let command = Filename.quote_command "date" ~stdout:tempfile ["+%S-%M-%H-%d-%m-%Y-%w-%j"] in
      let outcode = Sys.command command in
      if outcode > 0 then raise (Failure "Date command returned non-zero exit code") else
        let r = contents_of_file tempfile in
        let get_int o l = int_of_string (String.sub r o l) in
          Sys.remove tempfile;
          {_tm_sec = get_int 0 2;
           _tm_min = get_int 3 2;
           _tm_hour = get_int 6 2;
           _tm_mday = get_int 9 2;
           _tm_mon = get_int 12 2 - 1;
           _tm_year = get_int 15 4 - 1900;
           _tm_wday = get_int 20 1;
           _tm_yday = get_int 22 3 - 1;
           _tm_isdst = false}
   | "Win32" | "Cygwin" ->
      (* Run 'wmic os get LocalDateTime' (exists on XP Pro or later, Vista or later). *)
      let get_int r o l = int_of_string (String.sub r o l) in
      let tempfile = Filename.temp_file "cpdf" "strftime" in
      let command = Filename.quote_command "wmic.exe" ~stdout:tempfile ["os"; "get"; "LocalDateTime"] in
      let outcode = Sys.command command in
      if outcode > 0 then raise (Failure "wmic.exe os get LocalDateTime command returned non-zero exit code") else
        let r = contents_of_file tempfile in
        Sys.remove tempfile;
        let r = utf8_of_utf16le r in
      (* Run 'wmic path win32_localtime get dayofweek' (exists on XP Pro or later, Vista or later). *)
      let tempfile = Filename.temp_file "cpdf" "strftime" in
      let command = Filename.quote_command "wmic.exe" ~stdout:tempfile ["path"; "win32_localtime"; "get"; "dayofweek"] in
      let outcode = Sys.command command in
      if outcode > 0 then raise (Failure "wmic.exe path win32_localtime get dayofweek returned non-zero exit code") else
        let r2 = contents_of_file tempfile in
        Sys.remove tempfile;
        let r2 = utf8_of_utf16le r2 in
        let day = get_int r 35 2 in
        let month = get_int r 33 2 in
        let year = get_int r 29 4 in
        {_tm_sec = get_int r 41 2;
         _tm_min = get_int r 39 2;
         _tm_hour = get_int r 37 2;
         _tm_mday = day;
         _tm_mon = month - 1;
         _tm_year = year - 1900;
         _tm_wday = get_int r2 13 1;
         _tm_yday = year_day day month year - 1;
         _tm_isdst = false}
  | _ -> failwith "Unknown Sys.os_type in Cpdfstrftime.return_date"

let current_time () =
  try return_date () with
    e ->
      Pdfe.log (Printf.sprintf "Failed to retrieve time due to %s\n" (Printexc.to_string e));
      {_tm_sec = 0;
       _tm_min = 0;
       _tm_hour = 0;
       _tm_mday = 1;
       _tm_mon = 0;
       _tm_year = 0;
       _tm_wday = 0;
       _tm_yday = 0;
       _tm_isdst = false}

let strftime ?time text =
  let time =
    match time with None -> current_time () | Some t -> t
  in
    let text = ref text in
      iter
        (fun (search, replace_fun) ->
           text := string_replace_all search (replace_fun time) !text)
        strftime_pairs;
      !text