diff --git a/src/Clients/Goa.Clients.Dynamo.Generator/Attributes/AttributeHandlerRegistry.cs b/src/Clients/Goa.Clients.Dynamo.Generator/Attributes/AttributeHandlerRegistry.cs
index 70f43ea..46c85d2 100644
--- a/src/Clients/Goa.Clients.Dynamo.Generator/Attributes/AttributeHandlerRegistry.cs
+++ b/src/Clients/Goa.Clients.Dynamo.Generator/Attributes/AttributeHandlerRegistry.cs
@@ -61,26 +61,12 @@ private static bool IsAttributeApplicable(AttributeInfo attributeInfo, ISymbol s
type = named.TypeArguments[0];
}
- return IsDateTimeType(type);
+ return type.IsDateTimeOrDateTimeOffset();
}
return true;
}
- ///
- /// Determines whether the given type is System.DateTime or System.DateTimeOffset
- /// using robust symbol identity rather than brittle name comparisons.
- ///
- private static bool IsDateTimeType(ITypeSymbol type)
- {
- if (type.SpecialType == SpecialType.System_DateTime)
- return true;
-
- // DateTimeOffset has no SpecialType, so identify it by its fully-qualified name.
- return type.Name == nameof(DateTimeOffset)
- && type.ContainingNamespace?.ToDisplayString() == "System";
- }
-
///
/// Validates all attributes on a symbol and reports diagnostics.
///
diff --git a/src/Clients/Goa.Clients.Dynamo.Generator/Models/TypeSymbolExtensions.cs b/src/Clients/Goa.Clients.Dynamo.Generator/Models/TypeSymbolExtensions.cs
new file mode 100644
index 0000000..213e28c
--- /dev/null
+++ b/src/Clients/Goa.Clients.Dynamo.Generator/Models/TypeSymbolExtensions.cs
@@ -0,0 +1,23 @@
+using Microsoft.CodeAnalysis;
+
+namespace Goa.Clients.Dynamo.Generator.Models;
+
+///
+/// Helper extensions for inspecting Roslyn type symbols.
+///
+internal static class TypeSymbolExtensions
+{
+ ///
+ /// Determines whether the given type is System.DateTime or System.DateTimeOffset
+ /// using robust symbol identity rather than brittle name comparisons.
+ ///
+ public static bool IsDateTimeOrDateTimeOffset(this ITypeSymbol type)
+ {
+ if (type.SpecialType == SpecialType.System_DateTime)
+ return true;
+
+ // DateTimeOffset has no SpecialType, so identify it by its fully-qualified name.
+ return type.Name == nameof(DateTimeOffset)
+ && type.ContainingNamespace?.ToDisplayString() == "System";
+ }
+}
diff --git a/src/Clients/Goa.Clients.Dynamo.Generator/TypeHandlers/UnixTimestampTypeHandler.cs b/src/Clients/Goa.Clients.Dynamo.Generator/TypeHandlers/UnixTimestampTypeHandler.cs
index b429d80..cfe95d9 100644
--- a/src/Clients/Goa.Clients.Dynamo.Generator/TypeHandlers/UnixTimestampTypeHandler.cs
+++ b/src/Clients/Goa.Clients.Dynamo.Generator/TypeHandlers/UnixTimestampTypeHandler.cs
@@ -13,9 +13,8 @@ public bool CanHandle(PropertyInfo propertyInfo)
{
var underlyingType = propertyInfo.UnderlyingType;
var hasUnixTimestamp = propertyInfo.Attributes.Any(a => a is UnixTimestampAttributeInfo);
-
- return hasUnixTimestamp &&
- (underlyingType.Name == nameof(DateTime) || underlyingType.Name == nameof(DateTimeOffset));
+
+ return hasUnixTimestamp && underlyingType.IsDateTimeOrDateTimeOffset();
}
public string GenerateToAttributeValue(PropertyInfo propertyInfo)
diff --git a/tests/Clients/Goa.Clients.Dynamo.Generator.Tests/TypeHandlers/UnixTimestampTypeHandlerTests.cs b/tests/Clients/Goa.Clients.Dynamo.Generator.Tests/TypeHandlers/UnixTimestampTypeHandlerTests.cs
index 6ca862c..d85ba4f 100644
--- a/tests/Clients/Goa.Clients.Dynamo.Generator.Tests/TypeHandlers/UnixTimestampTypeHandlerTests.cs
+++ b/tests/Clients/Goa.Clients.Dynamo.Generator.Tests/TypeHandlers/UnixTimestampTypeHandlerTests.cs
@@ -1,3 +1,4 @@
+using Microsoft.CodeAnalysis;
using Goa.Clients.Dynamo.Generator.TypeHandlers;
using Goa.Clients.Dynamo.Generator.Tests.Helpers;
@@ -92,6 +93,33 @@ await Assert.That(result)
.IsFalse();
}
+ [Test]
+ public async Task CanHandle_WithUserDefinedTypeNamedDateTime_ShouldReturnFalse()
+ {
+ // Arrange: a user-defined type named "DateTime" outside the System namespace
+ // must not be treated as System.DateTime. The robust symbol-based check relies
+ // on SpecialType/namespace rather than the type name alone.
+ var spoofedDateTime = MockSymbolFactory.CreateNamedTypeSymbol(
+ "DateTime",
+ "MyApp.DateTime",
+ namespaceName: "MyApp",
+ specialType: SpecialType.None).Object;
+
+ var propertyInfo = TestModelBuilders.CreateUnixTimestampPropertyInfo(
+ "FakeTimestamp",
+ spoofedDateTime,
+ isNullable: false,
+ format: Models.UnixTimestampFormat.Seconds
+ );
+
+ // Act
+ var result = _handler.CanHandle(propertyInfo);
+
+ // Assert
+ await Assert.That(result)
+ .IsFalse();
+ }
+
[Test]
public async Task GenerateToAttributeValue_NonNullableDateTime_SecondsFormat_ShouldGenerateCorrectCode()
{