Skip to content

Commit

Permalink
Merge cddb94d into d82fc87
Browse files Browse the repository at this point in the history
  • Loading branch information
helgee committed Aug 12, 2018
2 parents d82fc87 + cddb94d commit 57ff97f
Show file tree
Hide file tree
Showing 22 changed files with 920 additions and 1,690 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ dist: trusty
language: julia
os:
- linux
# - osx
- osx
julia:
- 0.6
- 0.7
- nightly
matrix:
allow_failures:
Expand Down
9 changes: 4 additions & 5 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
julia 0.6
ItemGraphs 0.2.0
MuladdMacro 0.0.2
julia 0.7-beta
EarthOrientation 0.2.0
OptionalData 0.1.0
RemoteFiles 0.1.0
LeapSeconds 0.1.0
MuladdMacro 0.0.2
Reexport 0.1.0
4 changes: 2 additions & 2 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
environment:
matrix:
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.7/julia-0.7-latest-win32.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.7/julia-0.7-latest-win64.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"
matrix:
Expand Down
279 changes: 279 additions & 0 deletions src/AstroDates.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
module AstroDates

using ..TimeScales: TimeScale

import Base: time, show
import Dates

export Date, Time, DateTime,
year, month, day, j2000day, calendar,
hour, minute, second, date, time,
secondinday

abstract type Calendar end

struct ProlepticJulianCalendar <: Calendar end

struct JulianCalendar <: Calendar end

struct GregorianCalendar <: Calendar end

function findyear(::ProlepticJulianCalendar, j2000day)
-Int((-Int64(4) * j2000day - Int64(2920488)) ÷ Int64(1461))
end

function last_j2000_dayofyear(::ProlepticJulianCalendar, year)
365 * year + (year + 1) ÷ 4 - 730123
end

isleap(::ProlepticJulianCalendar, year) = (year % 4) == 0

function findyear(::JulianCalendar, j2000day)
-Int((-Int64(4) * j2000day - Int64(2921948)) ÷ Int64(1461))
end

function last_j2000_dayofyear(::JulianCalendar, year)
365 * year + year ÷ 4 - 730122
end

isleap(::JulianCalendar, year) = (year % 4) == 0

function findyear(::GregorianCalendar, j2000day)
year = Int((Int64(400) * j2000day + Int64(292194288)) ÷ Int64(146097))

# The previous estimate is one unit too high in some rare cases
# (240 days in the 400 years gregorian cycle, about 0.16%)
if j2000day <= last_j2000_dayofyear(GregorianCalendar(), year - 1)
year -= 1
end

year
end

function last_j2000_dayofyear(::GregorianCalendar, year)
365 * year + year ÷ 4 - year ÷ 100 + year ÷ 400 - 730120
end

function isleap(::GregorianCalendar, year)
year % 4 == 0 && (year % 400 == 0 || year % 100 != 0)
end

const PREVIOUS_MONTH_END_DAY_LEAP = (
0,
31,
60,
91,
121,
152,
182,
213,
244,
274,
305,
335,
)

const PREVIOUS_MONTH_END_DAY = (
0,
31,
59,
90,
120,
151,
181,
212,
243,
273,
304,
334,
)

function findmonth(dayinyear, isleap)
offset = isleap ? 313 : 323
dayinyear < 32 ? 1 : (10 * dayinyear + offset) ÷ 306
end

function findday(dayinyear, month, isleap)
previous_days = isleap ? PREVIOUS_MONTH_END_DAY_LEAP : PREVIOUS_MONTH_END_DAY
dayinyear - previous_days[month]
end

function finddayinyear(month, day, isleap)
previous_days = isleap ? PREVIOUS_MONTH_END_DAY_LEAP : PREVIOUS_MONTH_END_DAY
day + previous_days[month]
end

function getcalendar(year, month, day)
calendar = GregorianCalendar()
if year < 1583
if year < 1
calendar = ProlepticJulianCalendar()
elseif year < 1582 || month < 10 || (month < 11 && day < 5)
calendar = JulianCalendar()
end
end
calendar
end

struct Date{C}
year::Int
month::Int
day::Int
Date{C}(year, month, day) where {C} = new{C::Calendar}(year, month, day)
end

function Date(offset)
calendar = GregorianCalendar()
if offset < -152384
if offset > -730122
calendar = JulianCalendar()
else
calendar = ProlepticJulianCalendar()
end
end

year = findyear(calendar, offset)
dayinyear = offset - last_j2000_dayofyear(calendar, year - 1)

month = findmonth(dayinyear, isleap(calendar, year))
day = findday(dayinyear, month, isleap(calendar, year))

Date{calendar}(year, month, day)
end

function Date(epoch, offset)
Date(j2000day(epoch) + offset)
end

function Date(year, month, day)
check = Date(j2000day(year, month, day))
if check.year != year || check.month != month || check.day != day
throw(ArgumentError("Invalid date."))
end
Date{calendar(check)}(year, month, day)
end

year(s::Date) = s.year
month(s::Date) = s.month
day(s::Date) = s.day
calendar(s::Date{C}) where {C} = C

show(io::IO, d::Date) = print(io,
year(d), "-",
lpad(month(d), 2, '0'), "-",
lpad(day(d), 2, '0'))

Date(d::Dates.Date) = Date(Dates.year(d), Dates.month(d), Dates.day(d))
Dates.Date(d::Date) = Dates.Date(year(d), month(d), day(d))

function j2000day(calendar::Calendar, year, month, day)
last_j2000_dayofyear(calendar, year - 1) + finddayinyear(month, day, isleap(calendar, year))
end

function j2000day(year, month, day)
calendar = getcalendar(year, month, day)
j2000day(calendar, year, month, day)
end

j2000day(s::Date{C}) where {C} = j2000day(C, year(s), month(s), day(s))

julian(s::Date) = j2000day(s) + 2.451545e6

const JULIAN_EPOCH = Date(-4712, 1, 1)
const MODIFIED_JULIAN_EPOCH = Date(1858, 11, 17)
const FIFTIES_EPOCH = Date(1950, 1, 1)
const CCSDS_EPOCH = Date(1958, 1, 1)
const GALILEO_EPOCH = Date(1999, 8, 22)
const GPS_EPOCH = Date(1980, 1, 6)
const J2000_EPOCH = Date(2000, 1, 1)
const MIN_EPOCH = Date(typemin(Int32))
const MAX_EPOCH = Date(typemax(Int32))
const UNIX_EPOCH = Date(1970, 1, 1)

struct Time
hour::Int
minute::Int
second::Float64

function Time(hour, minute, second)
if hour < 0 || hour > 23
throw(ArgumentError("`hour` must be an integer between 0 and 23."))
elseif minute < 0 || minute > 59
throw(ArgumentError("`minute` must be an integer between 0 and 59."))
elseif second < 0 || second >= 61.0
throw(ArgumentError("`minute` must be a float between 0 and 60."))
end

new(hour, minute, second)
end
end

function Time(second_in_day_a, second_in_day_b)
carry = floor(Int, second_in_day_b)
wholeseconds = second_in_day_a + carry
fractional = second_in_day_b - carry

# range check
if wholeseconds < 0 || wholeseconds > 86400
throw(ArgumentError("Seconds are out of range"))
end

# extract the time components
hour = wholeseconds ÷ 3600
wholeseconds -= 3600 * hour
minute = wholeseconds ÷ 60
wholeseconds -= 60 * minute
second = wholeseconds + fractional

Time(hour, minute, second)
end

Time(t::Dates.Time) = Time(Dates.hour(t), Dates.minute(t), Dates.second(t))
Dates.Time(t::Time) = Dates.Time(hour(t), minute(t), second(t))

const H00 = Time(0, 0, 0.0)
const H12 = Time(12, 0, 0.0)

hour(s::Time) = s.hour
minute(s::Time) = s.minute
second(s::Time) = s.second

secondinday(t::Time) = t.second + 60 * t.minute + 3600 * t.hour

function show(io::IO, t::Time)
h = lpad(hour(t), 2, '0')
m = lpad(minute(t), 2, '0')
sec = second(t)
s = lpad(floor(Int, sec), 2, '0')
f = rpad(split(string(sec), '.')[end], 3, '0')[1:3]
print(io, h, ":", m, ":", s, ".", f)
end

struct DateTime{C}
date::Date{C}
time::Time
end

date(dt::DateTime) = dt.date
time(dt::DateTime) = dt.time

show(io::IO, dt::DateTime) = print(io, date(dt), "T", time(dt))

function DateTime(year, month, day, hour=0, minute=0, second=0.0)
DateTime(Date(year, month, day), Time(hour, minute, second))
end

year(dt::DateTime) = year(date(dt))
month(dt::DateTime) = month(date(dt))
day(dt::DateTime) = day(date(dt))
hour(dt::DateTime) = hour(time(dt))
minute(dt::DateTime) = minute(time(dt))
second(dt::DateTime) = second(time(dt))

DateTime(dt::Dates.DateTime) = DateTime(Dates.year(dt), Dates.month(dt), Dates.day(dt),
Dates.hour(dt), Dates.minute(dt), Dates.second(dt))
Dates.DateTime(dt::DateTime) = Dates.DateTime(year(dt), month(dt), day(dt),
hour(dt), minute(dt), second(dt))

end

Loading

0 comments on commit 57ff97f

Please sign in to comment.