diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 47cb950ce..35a7da52a 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -40,6 +40,7 @@ END TEMPLATE-->
### New features
* You can use `Subs.CVar()` from an entity systems to subscribe to CVar changes. This is more convenient than `IConfigurationManager.OnValueChanged` as it automatically unsubscribes on system shutdown.
+* There is now a built-in type serializer for `DateTime`, so you can put `DateTime`s in your data fields.
### Bugfixes
diff --git a/Robust.Shared/Serialization/TypeSerializers/Implementations/DateTimeSerializer.cs b/Robust.Shared/Serialization/TypeSerializers/Implementations/DateTimeSerializer.cs
new file mode 100644
index 000000000..7f62cf2b9
--- /dev/null
+++ b/Robust.Shared/Serialization/TypeSerializers/Implementations/DateTimeSerializer.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Globalization;
+using JetBrains.Annotations;
+using Robust.Shared.IoC;
+using Robust.Shared.Serialization.Manager;
+using Robust.Shared.Serialization.Manager.Attributes;
+using Robust.Shared.Serialization.Markdown;
+using Robust.Shared.Serialization.Markdown.Validation;
+using Robust.Shared.Serialization.Markdown.Value;
+using Robust.Shared.Serialization.TypeSerializers.Interfaces;
+
+namespace Robust.Shared.Serialization.TypeSerializers.Implementations;
+
+///
+/// Implements serialization for .
+///
+///
+/// Serialization is implemented with and the "o" format specifier.
+///
+[TypeSerializer]
+public sealed class DateTimeSerializer : ITypeSerializer, ITypeCopyCreator
+{
+ public ValidationNode Validate(
+ ISerializationManager serializationManager,
+ ValueDataNode node,
+ IDependencyCollection dependencies,
+ ISerializationContext? context = null)
+ {
+ return DateTime.TryParse(node.Value, null, DateTimeStyles.RoundtripKind, out _)
+ ? new ValidatedValueNode(node)
+ : new ErrorNode(node, "Failed parsing DateTime");
+ }
+
+ public DateTime Read(
+ ISerializationManager serializationManager,
+ ValueDataNode node,
+ IDependencyCollection dependencies,
+ SerializationHookContext hookCtx,
+ ISerializationContext? context = null,
+ ISerializationManager.InstantiationDelegate? instanceProvider = null)
+ {
+ return DateTime.Parse(node.Value, null, DateTimeStyles.RoundtripKind);
+ }
+
+ public DataNode Write(
+ ISerializationManager serializationManager,
+ DateTime value,
+ IDependencyCollection dependencies,
+ bool alwaysWrite = false,
+ ISerializationContext? context = null)
+ {
+ return new ValueDataNode(value.ToString("o"));
+ }
+
+ [MustUseReturnValue]
+ public DateTime CreateCopy(
+ ISerializationManager serializationManager,
+ DateTime source,
+ IDependencyCollection dependencies,
+ SerializationHookContext hookCtx,
+ ISerializationContext? context = null)
+ {
+ return source;
+ }
+}
diff --git a/Robust.UnitTesting/Shared/Serialization/TypeSerializers/DateTimeSerializerTest.cs b/Robust.UnitTesting/Shared/Serialization/TypeSerializers/DateTimeSerializerTest.cs
new file mode 100644
index 000000000..39853217f
--- /dev/null
+++ b/Robust.UnitTesting/Shared/Serialization/TypeSerializers/DateTimeSerializerTest.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Globalization;
+using NUnit.Framework;
+using Robust.Shared.Serialization.Manager;
+using Robust.Shared.Serialization.Markdown.Value;
+using Robust.Shared.Serialization.TypeSerializers.Implementations;
+
+namespace Robust.UnitTesting.Shared.Serialization.TypeSerializers;
+
+[TestFixture]
+[TestOf(typeof(DateTimeSerializer))]
+internal sealed class DateTimeSerializerTest : SerializationTest
+{
+ [Test]
+ public void WriteTest()
+ {
+ var dateTime = DateTime.UtcNow;
+ var result = Serialization.WriteValueAs(dateTime);
+
+ var parsed = DateTime.Parse(result.Value, null, DateTimeStyles.RoundtripKind);
+ Assert.That(parsed, Is.EqualTo(dateTime));
+ }
+
+ [Test]
+ public void ReadTest()
+ {
+ var result = Serialization.Read(new ValueDataNode("2020-07-10 15:00:00.000"));
+
+ Assert.That(result, Is.EqualTo(new DateTime(2020, 07, 10, 15, 0, 0)));
+ }
+}