#lang typed-scheme
(define-type-alias Time-Type (U 'time-duration
                                'time-monotonic
                                'time-process
                                'time-tai
                                'time-thread
                                'time-utc))

(require/opaque-type Time time? srfi/19)
(require/opaque-type Date date? srfi/19)

(define-type-alias Time-Monotonic Time)
(define-type-alias Time-TAI Time)
(define-type-alias Time-UTC Time)
(define-type-alias Time-Duration Time)

(define-type-alias JD  Number)
(define-type-alias MJD Number)

(require/typed srfi/19
               ;; Constants
               [time-duration  Time-Type]
               [time-monotonic Time-Type]
               [time-process   Time-Type]
               [time-tai       Time-Type]
               [time-thread    Time-Type]
               [time-utc       Time-Type]
               
               ;; Current time and clock resolution
               [current-date
                (case-lambda (-> Date)
                             (Integer -> Date))]
               [current-julian-day (-> JD)]
               [current-modified-julian-day (-> MJD)]
               [current-time 
                (case-lambda (-> Time)
                             (Time-Type -> Time))]
               [time-resolution 
                (case-lambda (-> Integer)
                             (Time-Type -> Integer))]
               
               ;; Time object and accessors
               [make-time (Time-Type Integer Integer -> Time)]
               [time-type (Time -> Time-Type)]
               [time-nanosecond (Time -> Integer)]
               [time-second (Time -> Integer)]
               [set-time-type! (Time Time-Type -> Void)]
               [set-time-nanosecond! (Time Integer -> Void)]
               [set-time-second! (Time Integer -> Void)]
               [copy-time (Time -> Time)]
               
               ;; Time comparison procedures
               [time<=? (Time Time -> Boolean)]
               [time<?  (Time Time -> Boolean)]
               [time=?  (Time Time -> Boolean)]
               [time>=? (Time Time -> Boolean)]
               [time>?  (Time Time -> Boolean)]
               
               ;; Time arithmetic procedures
               [time-difference  (Time Time -> Time-Duration)]
               [time-difference! (Time Time -> Time-Duration)]
               [add-duration  (Time Time-Duration -> Time)]
               [add-duration! (Time Time-Duration -> Time)]
               [subtract-duration  (Time Time-Duration -> Time)]
               [subtract-duration! (Time Time-Duration -> Time)]
               
               ;; Date object and accessors
               [make-date 
                (Integer Integer Integer Integer 
                         Integer Integer Integer Integer -> Date)]
               [date-nanosecond  (Date -> Integer)]
               [date-second      (Date -> Integer)]
               [date-minute      (Date -> Integer)]
               [date-hour        (Date -> Integer)]
               [date-day         (Date -> Integer)]
               [date-month       (Date -> Integer)]
               [date-year        (Date -> Integer)]
               [date-zone-offset (Date -> Integer)]
               [date-year-day    (Date -> Integer)]
               [date-week-day    (Date -> Integer)]
               [date-week-number (Date Integer -> Integer)]
               
               ;; Time/Date/Julian Day/Modified Julian Day Converters
               [date->julian-day (Date -> JD)]
               [date->modified-julian-day (Date -> MJD)]
               [date->time-monotonic (Date -> Time-Monotonic)]
               [date->time-tai       (Date -> Time-TAI)]
               [date->time-utc       (Date -> Time-UTC)]
               [julian-day->date
                (case-lambda (JD -> Date)
                             (JD Integer -> Date))]
               [julian-day->time-monotonic (JD -> Time-Monotonic)]
               [julian-day->time-tai       (JD -> Time-TAI)]
               [julian-day->time-utc       (JD -> Time-UTC)]
               [modified-julian-day->date
                (case-lambda (MJD -> Date)
                             (MJD Integer -> Date))]
               [modified-julian-day->time-monotonic (MJD -> Time-Monotonic)]
               [modified-julian-day->time-tai       (MJD -> Time-TAI)]
               [modified-julian-day->time-utc       (MJD -> Time-UTC)]
               [time-monotonic->date (Time-Monotonic Integer -> Date)]
               [time-monotonic->julian-day (Time-Monotonic -> JD)]
               [time-monotonic->modified-julian-day (Time-Monotonic -> MJD)]
               [time-monotonic->time-tai  (Time-Monotonic -> Time-TAI)]
               [time-monotonic->time-tai! (Time-Monotonic -> Time-TAI)]
               [time-monotonic->time-utc  (Time-Monotonic -> Time-UTC)]
               [time-monotonic->time-utc! (Time-Monotonic -> Time-UTC)]
               [time-tai->date 
                (case-lambda (Time-TAI -> Date)
                             (Time-TAI Integer -> Date))]
               [time-tai->julian-day (Time-TAI -> JD)]
               [time-tai->modified-julian-day (Time-TAI -> MJD)]
               [time-tai->time-monotonic  (Time-TAI -> Time-Monotonic)]
               [time-tai->time-monotonic! (Time-TAI -> Time-Monotonic)]
               [time-tai->time-utc  (Time-TAI -> Time-UTC)]
               [time-tai->time-utc! (Time-TAI -> Time-UTC)]
               [time-utc->date (Time-UTC -> Date)]
               [time-utc->julian-day (Time-UTC -> JD)]
               [time-utc->modified-julian-day (Time-UTC -> MJD)]
               [time-utc->time-monotonic  (Time-UTC -> Time-Monotonic)]
               [time-utc->time-monotonic! (Time-UTC -> Time-Monotonic)]
               [time-utc->time-tai  (Time-UTC -> Time-TAI)]
               [time-utc->time-tai! (Time-UTC -> Time-TAI)]
               
               ;; Date to String/String to Date Converters
               [date->string 
                (case-lambda (Date -> String)
                             (Date String -> String))]
               [string->date (String String -> Date)]
               
               ) ; end of require/typed

(provide
 ;; Constants
 time-duration
 time-monotonic 
 time-process
 time-tai
 time-thread
 time-utc
 
 ;; Current time and clock resolution
 current-date
 current-julian-day
 current-modified-julian-day 
 current-time 
 time-resolution
 
 ;; Time object and accessors
 make-time 
 time?
 time-type
 time-nanosecond
 time-second
 set-time-type!
 set-time-nanosecond!
 set-time-second!
 copy-time
 
 ;; Time comparison procedures
 time<=?
 time<?
 time=?
 time>=?
 time>?
 
 ;; Time arithmetic procedures
 time-difference
 time-difference!
 add-duration
 add-duration!
 subtract-duration
 subtract-duration!
 
 ;; Date object and accessors
 make-date 
 date?
 date-nanosecond
 date-second
 date-minute
 date-hour
 date-day
 date-month
 date-year
 date-zone-offset
 date-year-day
 date-week-day
 date-week-number
 
 ;; Time/Date/Julian Day/Modified Julian Day Converters
 date->julian-day
 date->modified-julian-day
 date->time-monotonic
 date->time-tai
 date->time-utc
 julian-day->date
 julian-day->time-monotonic
 julian-day->time-tai
 julian-day->time-utc
 modified-julian-day->date
 modified-julian-day->time-monotonic
 modified-julian-day->time-tai
 modified-julian-day->time-utc
 time-monotonic->date
 time-monotonic->julian-day
 time-monotonic->modified-julian-day
 time-monotonic->time-tai
 time-monotonic->time-tai!
 time-monotonic->time-utc
 time-monotonic->time-utc!
 time-tai->date 
 time-tai->julian-day
 time-tai->modified-julian-day
 time-tai->time-monotonic
 time-tai->time-monotonic!
 time-tai->time-utc
 time-tai->time-utc!
 time-utc->date
 time-utc->julian-day
 time-utc->modified-julian-day
 time-utc->time-monotonic
 time-utc->time-monotonic!
 time-utc->time-tai
 time-utc->time-tai!
 
 ;; Date to String/String to Date Converters
 date->string
 string->date 
 
 ) ; end of provide

