nicfit / eyeD3

eyeD3 is a Python module and command line program for processing ID3 tags. Information about mp3 files (i.e bit rate, sample frequency, play time, etc.) is also provided. The formats supported are ID3v1 (1.0/1.1) and ID3v2 (2.3/2.4).
http://eyed3.nicfit.net/
GNU General Public License v3.0
540 stars 58 forks source link

Passing eyed3.core.Date to recording_date still results in Invalid date text: ... #517

Open iarp opened 3 years ago

iarp commented 3 years ago

I'm a touch lost as to where to go from here. I need to set the recording_date value to a specific date. I've tried as a string, datetime.datetime, and even eyed3.core.Date objects and all fail in some way.

import eyed3
from eyed3.core import Date
af = eyed3.load(file.path)
dt = file.show_date
print(dt)
af.tag.recording_date = Date(dt.year, dt.month, dt.day)

I don't even have to save, it just spits out the following error

1986-05-04
Invalid date text: 0405

If I do save it only saves the year.

I could understand the error if I were passing a string that you had to parse and attempt to figure out its format, but I'm literally passing it eyed3's own Date object with a specific year month and day, how could it be failing?

Edit: Forgot to mention its id3v2.3

iarp commented 3 years ago

Decided to just change https://github.com/nicfit/eyeD3/blob/master/eyed3/id3/tag.py#L558 to the following and it works fine.

self._setDate(b"TDAT", date)
TwoLeaves commented 1 year ago

Yep, I get this error too when setting dates with the day of the month being less than 10. So setting "recording-date" to "2020-12-25" works but "2020-12-08" fails (or rather just sets the year). Your fix works: replacing "self._setDate(b"TYER", str(date.year))" with "self._setDate(b"TYER", str(date))".

TJ-59 commented 6 months ago

@iarp @TwoLeaves If you're still using eyed3, this #623 might be the solution for your problem.

brandonscript commented 5 months ago

I ended up doing this and calling it as a standalone function. I don't know much here, but I thought TDRC was v2.4+, but I keep finding examples where v2.3 won't accept TYER, TDAT.

def _setRecordingDate(tag: Tag, date: str | core.Date | None) -> None:
    if date in (None, ""):
        for fid in (b"TDRC", b"TYER", b"TDAT", b"TIME"):
            tag._setDate(fid, None)
    elif tag.version == ID3_V2_4 or tag.version == ID3_V2_3:
        try:
            tag._setDate(b"TDRC", date)
        except ValueError:
            pass
    else:
        if not isinstance(date, core.Date):
            parsed_date = core.Date.parse(date)
        else:
            parsed_date = date

        year = parsed_date.year
        month = parsed_date.month
        day = parsed_date.day

        if year is not None:
            tag._setDate(b"TYER", str(year))
        if None not in (month, day):
            date_str = "%s%s" % (str(day).rjust(2, "0"), str(month).rjust(2, "0"))
            tag._setDate(b"TDAT", date_str)
TJ-59 commented 5 months ago

@brandonscript yep, TDRC IS for v2.4+, it contains all the different parts, whereas previous date tags (TYER,TDAT,TIME) are used in version prior and up to v2.3. Have a read of the #623 I posted if you need some clarity , I explain what happens and quote the official docs on those specific frames. A bit longer than most would like for a pull request comment, but plenty to learn about how it's done inside eyed3.