beacon-biosignals / EDF.jl

Read and write EDF files in Julia
MIT License
18 stars 5 forks source link

Try to snap month and/or day in header date to 01 if not in valid range. #34

Closed kolia closed 4 years ago

kolia commented 4 years ago

EDF does not specify what to do if the month or day is not in a valid range so if it is not this snaps the month or day to "01" and tries to parse again.

ararslan commented 4 years ago

Rather than using exception handling to determine the issue here, I'd do something like

function parse_header_date(date_str::AbstractString)
    dt = tryparse(DateTime, date_str, dateformat"dd\.mm\.yy HH\.MM\.SS")
    dt === nothing || return dt
    m = match(r"^(\d{2})\.(\d{2})\.(\d{2}) (\d{2})\.(\d{2})\.(\d{2})$", date_str)
    if m === nothing
        # Maybe it would be better to return `missing` here? Not sure.
        throw(ArgumentError("Malformed date string: expected 'dd.mm.yy HH.MM.SS', " *
                            "got '$date_str'"))
    end
    day, month, year, hour, minute, second = parse.(Int, m.captures)
    if year <= 84
        year += 2000
    else
        year += 1900
    end
    month = clamp(month, 1, 12)
    day = clamp(day, 1, daysinmonth(year, month))
    hour = clamp(hour, 1, 24)
    minute = clamp(minute, 1, 60)
    second = clamp(second, 1, 60)
    return DateTime(year, month, day, hour, minute, second)
end

This ensures that all values are in range, since any one of the six values in play here could be the culprit if parsing fails.

ararslan commented 4 years ago

As a very minor aside, per this section in the engineering practices, the branch name prefix here should be ks. :slightly_smiling_face:

kolia commented 4 years ago

Nice, I didn't know about Dates.daysinmonth, hence repeatedly trying to parse and see if the date was valid.

That's both clearer and more general.