Skip to content

Commit

Permalink
Merge pull request #16 from TidierOrg/add-warnings
Browse files Browse the repository at this point in the history
Add warnings
  • Loading branch information
drizk1 authored Sep 14, 2024
2 parents 29369f1 + a3e32c3 commit a46e317
Show file tree
Hide file tree
Showing 9 changed files with 260 additions and 64 deletions.
5 changes: 3 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
name = "TidierDates"
uuid = "20186a3f-b5d3-468e-823e-77aae96fe2d8"
authors = ["Daniel Rizk & Contributors"]
version = "0.2.5"
version = "0.2.6"


[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Expand All @@ -10,8 +11,8 @@ TimeZones = "f269a46b-ccf7-5d73-abea-4c690281aa53"

[compat]
Reexport = "0.2, 1"
julia = "1.9"
TimeZones = "1.17"
julia = "1.9"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Pkg.add(url = "https://github.com/TidierOrg/TidierDates.jl.git")

#### `mdy()`, `dmy()`, `ymd()`

These functions parse dates represented as strings into a DateTime format in Julia. The input should be a string month-day-year, day-month-year, or year-month-day format respectively. They are relatively robust in their ability to take non-uniform strings of dates.
These functions parse dates represented as strings into a DateTime format in Julia. The input should be a string month-day-year, day-month-year, or year-month-day format respectively. They are relatively robust in their ability to take non-uniform strings of dates. English, Spanish, Portuguese, and French months and abbreviations are supported.

```julia
using TidierData
Expand Down
2 changes: 2 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ In addition, this package includes:
- `am()`, `pm()`
- `leap_year()`
- `days_in_month()`

English, Spanish, Portuguese and French months and abbreviations are supported.
50 changes: 30 additions & 20 deletions src/TidierDates.jl
Original file line number Diff line number Diff line change
@@ -1,29 +1,19 @@
module TidierDates

using Dates, Reexport, TimeZones
#Unicode

@reexport using Dates

include("datedocstrings.jl")

include("month_dicts.jl")
export mdy, mdy_hms, dmy, dmy_hms, ymd, ymd_hms, ymd_h, ymd_hm,
hms, difftime, floor_date, round_date, now, today, am, pm, leap_year,
days_in_month, dmy_h, dmy_hm, mdy_h, mdy_hm

#### Create dictionaries to map full and abbreviated month names to numbers
full_month_to_num = Dict{String, Int}(
"JANUARY" => 1, "FEBUARY" => 2, "MARCH" => 3, "APRIL" => 4,
"MAY" => 5, "JUNE" => 6, "JULY" => 7, "AUGUST" => 8,
"SEPTEMBER" => 9, "OCTOBER" => 10, "NOVEMBER" => 11, "DECEMBER" => 12
)

abbreviated_month_to_num = Dict{String, Int}(
"JAN" => 1, "FEB" => 2, "MAR" => 3, "APR" => 4,
"MAY" => 5, "JUN" => 6, "JUL" => 7, "AUG" => 8,
"SEP" => 9, "OCT" => 10, "NOV" => 11, "DEC" => 12
)

function replace_month_with_number(datetime_string::String)
days_in_month, dmy_h, dmy_hm, mdy_h, mdy_hm, hm


function replace_month_with_number(datetime_string::Union{String, SubString{String}})

# Replace full month names
for (month, num) in full_month_to_num
datetime_string = replace(datetime_string, month => string(num))
Expand Down Expand Up @@ -70,7 +60,7 @@ end
"""
$docstring_floor_date
"""
function floor_date(dt::Union{DateTime, Missing}, unit::String)
function floor_date(dt::Union{DateTime, Date, Time, Missing}, unit::String)
if ismissing(dt)
return missing
end
Expand All @@ -80,8 +70,13 @@ function floor_date(dt::Union{DateTime, Missing}, unit::String)
elseif unit == "month"
return floor(dt, Month)
elseif unit == "week"
start_of_week = firstdayofweek(dt) - Day(1)
return floor(start_of_week, Day)
if dayofweek(dt) != 7
start_of_week = floor(dt, Week)
start_of_week -= Day(1)
return start_of_week
else
return dt
end
elseif unit == "day"
return floor(dt, Day)
elseif unit == "hour"
Expand Down Expand Up @@ -243,4 +238,19 @@ function days_in_month(dt::TimeType)::Int
return daysinmonth(dt)
end


"""
$docstring_hm
"""
function hm(time_string::Union{AbstractString, Missing})
if ismissing(time_string)
return missing
end
try
return Time(time_string, "HH:MM")
catch
return missing
end
end

end
39 changes: 36 additions & 3 deletions src/datedocstrings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ julia> mdy("01 24 2023")
julia> mdy(missing)
missing
julia> mdy("FÉVRIER 20 2020") # French
2020-02-20
```
"""

Expand Down Expand Up @@ -63,6 +66,13 @@ julia> dmy("3rd of December, 2020")
julia> dmy(missing)
missing
julia> dmy("20 DICIEMBRE 2020") # Spanish
2020-12-20
julia> dmy("21 MARÇO 2014") # Portuguese
2014-03-21
```
"""

Expand Down Expand Up @@ -131,7 +141,7 @@ Round down a DateTime object to the nearest specified unit.
# Returns
The DateTime object rounded down to the nearest specified unit. If the input is missing, the function returns a missing value.
When using the "week" unit, Sunday is considered the first day of the week.
When using the "week" unit, Sunday is considered the first day of the week, and if the date is already a Sunday, it is returned as is.
# Examples
```jldoctest
Expand Down Expand Up @@ -401,7 +411,6 @@ false
julia> leap_year(2020)
true
```
"""

const docstring_days_in_month =
Expand Down Expand Up @@ -579,7 +588,8 @@ A DateTime object constructed from the parsed month, day, year, and hour values
julia> mdy_hm("06-15-2023 09:03 P")
2023-06-15T21:03:00
julia> mdy_hm("06-15-2023 09:03 p")
julia> mdy_hm("june 15 2023 09:03 p")
2023-06-15T21:03:00
julia> mdy_hm("06-15-2023 09:03 ")
2023-06-15T09:03:00
Expand All @@ -589,4 +599,27 @@ julia> mdy_hm("june 15 2023 09:03 p")
julia> mdy_hm(missing)
missing
```
"""

const docstring_hm =
"""
hm(time_string::Union{AbstractString, Missing})::Time
Converts a time string in the format "HH:MM" to a Time object.
# Arguments
`time_string`: A string containing a time representation.
# Returns
A Time object constructed from the parsed hour and minute values from the input string, if all can be parsed successfully. Returns a missing value if the input is missing or if the time information cannot be parsed from the string.
# Examples
```jldoctest
julia> hm("09:30")
09:30:00
julia> hm("12:60")
missing
```
"""
62 changes: 41 additions & 21 deletions src/dmys.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,54 +10,63 @@ function dmy(date_string::Union{AbstractString, Missing})
date_string = strip(replace(date_string, r"ST|ND|RD|TH|,|OF|THE" => ""))
date_string = replace(date_string, r"\s+" => Base.s" ")
end
# Match for "ddmmyyyy" format
m = match(r"(\d{1,2})(\d{1,2})(\d{4})", date_string)

# Match for "ddmmyyyy" or "ddmmyy" format
m = match(r"^(\d{1,2})(\d{1,2})(\d{2,4})$", date_string)
if m !== nothing
day_str, month_str, year_str = m.captures
day = parse(Int, day_str)
month = parse(Int, month_str)
year = parse(Int, year_str)
if length(year_str) == 2
if year > 30
year += 1900
else
year += 2000
end
end
return Date(year, month, day)
end

# Match for "dd Month yyyy" format
m = match(r"(\d{1,2}) (\d{1,2}) (\d{4})", date_string)
# Match for "dd mm yyyy" or "dd mm yy" format
m = match(r"^(\d{1,2}) (\d{1,2}) (\d{2,4})$", date_string)
if m !== nothing
day_str, month_str, year_str = m.captures
day = parse(Int, day_str)
month = parse(Int, month_str)
year = parse(Int, year_str)
return Date(year, month, day)
end

# Match for "Month dd, yyyy" format
m = match(r"(\d{1,2})(ST|ND|RD|TH)?\s*(\w+)\s*(\d{4})", date_string)
if m !== nothing
day_str, _, month_str, year_str = m.captures
day = parse(Int, day_str)
year = parse(Int, year_str)
month = tryparse(Int, month_str)
if month === nothing
return missing
if length(year_str) == 2
if year > 30
year += 1900
else
year += 2000
end
end
return Date(year, month, day)
end

# Match for "dd-mm-yyyy" or "dd/mm/yyyy" format
m = match(r"(\d{1,2})[/-](\d{1,2})[/-](\d{4})", date_string)
# Match for "dd-mm-yyyy", "dd/mm/yyyy", "dd-mm-yy", or "dd/mm/yy" format
m = match(r"^(\d{1,2})[/-](\d{1,2})[/-](\d{2,4})$", date_string)
if m !== nothing
day_str, month_str, year_str = m.captures
day = parse(Int, day_str)
month = parse(Int, month_str)
year = parse(Int, year_str)
if length(year_str) == 2
if year > 30
year += 1900
else
year += 2000
end
end
return Date(year, month, day)
end

return missing
end



"""
$docstring_dmy_hms
"""
Expand Down Expand Up @@ -145,10 +154,20 @@ function dmy_hm(datetime_string::Union{AbstractString, Missing})
month = parse(Int, month_str)
year = parse(Int, year_str)
hour = parse(Int, hour_str)
if hour <= 12 && occursin(r"(?<![A-Za-z])[Pp](?:[Mm])?(?![A-Za-z])", datetime_string)
minute = parse(Int, minute_str)
if minute == 60
@warn "Minute is 60, returning missing"
return missing
end
# Handle AM/PM format
if hour <= 12 && occursin(r"(?<![A-Za-z])[Pp](?:[Mm])?(?![A-Za-z])", datetime_string)
hour += 12
end
minute = parse(Int, minute_str)

# Handle the case when hour is 24 by incrementing the date and setting time to 00:xx
if hour == 24
return DateTime(year, month, day, 0, minute) + Day(1)
end

# Return as DateTime
return DateTime(year, month, day, hour, minute)
Expand All @@ -157,3 +176,4 @@ function dmy_hm(datetime_string::Union{AbstractString, Missing})
# If no match found, return missing
return missing
end

Loading

0 comments on commit a46e317

Please sign in to comment.