diff --git a/src/TaglibSharp.Tests/TaggingFormats/Id3V2Test.cs b/src/TaglibSharp.Tests/TaggingFormats/Id3V2Test.cs
index 6c6b2381..c1b34f06 100644
--- a/src/TaglibSharp.Tests/TaggingFormats/Id3V2Test.cs
+++ b/src/TaglibSharp.Tests/TaggingFormats/Id3V2Test.cs
@@ -18,6 +18,8 @@ public class Id3V2Test
static readonly string[] val_gnre = {"Rap",
"Jazz", "Non-Genre", "Blues"};
+ static readonly System.DateTime val_date = new System.DateTime (2022, 10, 20, 16, 45, 23, 0, 0);
+
[Test]
public void TestTitle ()
{
@@ -1024,6 +1026,35 @@ public void TestPublisher ()
}
}
+
+ [Test]
+ public void TestEncodedBy ()
+ {
+ Tag tag = new Tag ();
+ for (byte version = 2; version <= 4; version++) {
+ tag.Version = version;
+
+ TagTestWithSave (ref tag, delegate (Tag t, string m) {
+ Assert.IsTrue (t.IsEmpty, "Initial (IsEmpty): " + m);
+ Assert.IsNull (t.EncodedBy, "Initial (Null): " + m);
+ });
+
+ tag.EncodedBy = val_sing;
+
+ TagTestWithSave (ref tag, delegate (Tag t, string m) {
+ Assert.IsFalse (t.IsEmpty, "Value Set (!IsEmpty): " + m);
+ Assert.AreEqual (val_sing, t.EncodedBy, "Value Set (!Null): " + m);
+ });
+
+ tag.EncodedBy = string.Empty;
+
+ TagTestWithSave (ref tag, delegate (Tag t, string m) {
+ Assert.IsTrue (t.IsEmpty, "Value Cleared (IsEmpty): " + m);
+ Assert.IsNull (t.EncodedBy, "Value Cleared (Null): " + m);
+ });
+ }
+ }
+
[Test]
public void TestISRC ()
{
@@ -1052,6 +1083,34 @@ public void TestISRC ()
}
}
+ [Test]
+ public void TestReleaseDate ()
+ {
+ Tag tag = new Tag ();
+ for (byte version = 4; version <= 4; version++) {
+ tag.Version = version;
+
+ TagTestWithSave (ref tag, delegate (Tag t, string m) {
+ Assert.IsTrue (t.IsEmpty, "Initial (IsEmpty): " + m);
+ Assert.IsNull (t.ReleaseDate, "Initial (Null): " + m);
+ }, 4);
+
+ tag.ReleaseDate = val_date;
+
+ TagTestWithSave (ref tag, delegate (Tag t, string m) {
+ Assert.IsFalse (t.IsEmpty, "Value Set (!IsEmpty): " + m);
+ Assert.AreEqual (val_date, t.ReleaseDate.Value, "Value Set (!Null): " + m);
+ }, 4);
+
+ tag.ReleaseDate = null;
+
+ TagTestWithSave (ref tag, delegate (Tag t, string m) {
+ Assert.IsTrue (t.IsEmpty, "Value Cleared (IsEmpty): " + m);
+ Assert.IsNull (t.ReleaseDate, "Value Cleared (Null): " + m);
+ }, 4);
+ }
+ }
+
[Test]
public void TestLength ()
{
@@ -1738,10 +1797,10 @@ public void TestInvolvedPersonsFrame ()
delegate void TagTestFunc (Tag tag, string msg);
- void TagTestWithSave (ref Tag tag, TagTestFunc testFunc)
+ void TagTestWithSave (ref Tag tag, TagTestFunc testFunc, byte minVersion = 2)
{
testFunc (tag, "Before Save");
- for (byte version = 2; version <= 4; version++) {
+ for (byte version = minVersion; version <= 4; version++) {
tag.Version = version;
tag = new Tag (tag.Render ());
testFunc (tag, "After Save, Version: " + version);
diff --git a/src/TaglibSharp/Id3v2/FrameTypes.cs b/src/TaglibSharp/Id3v2/FrameTypes.cs
index e430af85..62a477a6 100644
--- a/src/TaglibSharp/Id3v2/FrameTypes.cs
+++ b/src/TaglibSharp/Id3v2/FrameTypes.cs
@@ -101,6 +101,8 @@ static class FrameType
public static readonly ReadOnlyByteVector WPUB = "WPUB";
public static readonly ReadOnlyByteVector WXXX = "WXXX";
public static readonly ReadOnlyByteVector ETCO = "ETCO";
+ public static readonly ReadOnlyByteVector TDRL = "TDRL"; // Release Time Frame
+ public static readonly ReadOnlyByteVector TENC = "TENC"; // Encoded By Frame.
public static readonly ReadOnlyByteVector MVNM = "MVNM"; // Movement Name
public static readonly ReadOnlyByteVector MVIN = "MVIN"; // Movement Number/Count
}
diff --git a/src/TaglibSharp/Id3v2/Tag.cs b/src/TaglibSharp/Id3v2/Tag.cs
index cd669dc0..4f666e9b 100644
--- a/src/TaglibSharp/Id3v2/Tag.cs
+++ b/src/TaglibSharp/Id3v2/Tag.cs
@@ -2299,6 +2299,20 @@ public override string Publisher {
set { SetTextFrame (FrameType.TPUB, value); }
}
+ ///
+ /// Gets and sets the TENC (Encoded by) of the song.
+ ///
+ ///
+ /// A object containing the TENC of the song.
+ ///
+ ///
+ /// This property is implemented using the "TENC" field.
+ ///
+ public string EncodedBy {
+ get { return GetTextAsString (FrameType.TENC); }
+ set { SetTextFrame (FrameType.TENC, value); }
+ }
+
///
/// Gets and sets the ISRC (International Standard Recording Code) of the song.
///
@@ -2313,6 +2327,48 @@ public override string ISRC {
set { SetTextFrame (FrameType.TSRC, value); }
}
+ ///
+ /// Gets and sets the date at which the song has been released.
+ ///
+ ///
+ /// A nullable object containing the
+ /// date at which the song has been released, or if no value present.
+ ///
+ ///
+ /// This property is implemented using the "TDRL" field.
+ /// This is a ID3v2.4 type tag.
+ ///
+ public DateTime? ReleaseDate {
+ get {
+ string value = GetTextAsString (FrameType.TDRL);
+
+ if (String.IsNullOrWhiteSpace(value)) {
+ return null;
+ } else if (DateTime.TryParseExact (value.Replace ('T', ' '), "yyyy-MM-dd HH:mm:ss", null, DateTimeStyles.None, out DateTime exactDate)) {
+ return exactDate;
+ } else if (DateTime.TryParse(value, out DateTime parsedDate)) {
+ return parsedDate;
+ }
+
+ return null;
+ }
+ set {
+ string date = null;
+
+ if (value != null) {
+ date = $"{value:yyyy-MM-dd HH:mm:ss}";
+ date = date.Replace (' ', 'T');
+ }
+
+ if (date == null) {
+ RemoveFrames(FrameType.TDRL);
+ } else {
+ SetTextFrame(FrameType.TDRL, date);
+ }
+ }
+ }
+
///
/// Gets and sets the length of the media represented
/// by the current instance.