XINCGer/Unity3DTraining · error · ArgumentException
Conversion from DateTime to Timestamp requires the DateTime…
Error message
Conversion from DateTime to Timestamp requires the DateTime kind to be Utc
What it means
Timestamp.FromDateTime only accepts DateTime values whose Kind is DateTimeKind.Utc; anything Local or Unspecified is rejected with ArgumentException because the conversion to Unix-epoch seconds would silently misinterpret the wall-clock time. The library forces callers to convert explicitly rather than guessing a time zone.
Solutions
- Use DateTime.UtcNow or call dateTime.ToUniversalTime() before FromDateTime
- For Unspecified values you know are UTC, use DateTime.SpecifyKind(dt, DateTimeKind.Utc)
- For local wall-clock times with a known zone, convert with TimeZoneInfo.ConvertTimeToUtc(dt, zone) first
- Prefer DateTimeOffset and Timestamp.FromDateTimeOffset when offsets are available
Example fix
// before
var ts = Timestamp.FromDateTime(DateTime.Now); // throws: Kind is Local
// after
var ts2 = Timestamp.FromDateTime(DateTime.UtcNow);
// or for a parsed value known to be UTC:
var parsed = DateTime.Parse("2024-01-01T12:00:00Z").ToUniversalTime();
var ts3 = Timestamp.FromDateTime(parsed); Defensive patterns
Strategy: try-catch
Validate before calling
static DateTime EnsureUtc(DateTime dt) => dt.Kind == DateTimeKind.Utc ? dt : dt.ToUniversalTime();
Type guard
static bool IsUtc(DateTime dt) => dt.Kind == DateTimeKind.Utc;
Try / catch
try { return Timestamp.FromDateTime(dt); } catch (ArgumentException ex) { log.Warn(ex, "Non-UTC DateTime Kind={Kind}", dt.Kind); return Timestamp.FromDateTime(dt.ToUniversalTime()); } Prevention
- Use DateTime.UtcNow everywhere internally
- After DateTime.Parse, call .ToUniversalTime() immediately
- Use DateTimeOffset end-to-end to preserve offset information
When it happens
Trigger: Calling FromDateTime (directly or via FromDateTimeOffset with a non-UTC offset) with dateTime.Kind == Local (e.g. DateTime.Now) or Unspecified (e.g. parsed from a string without offset info).
Common situations: Passing DateTime.Now instead of DateTime.UtcNow; strings parsed with DateTime.Parse producing Unspecified kind; values read from databases configured with local time; legacy code that stores local wall-clock times.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Timestamp contains invalid values: Seconds=
- Non-normalized timestamp value
- Expected string value for Timestamp
- Invalid Timestamp value
- Non-normalized duration value
AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12).
Data as JSON: /api/errors/c4888faf4122ae6e.
Report an issue: GitHub.
Appendix: source
Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/WellKnownTypes/TimestampPartial.cs:152
/// <returns>This timestamp as a <c>DateTimeOffset</c>.</returns>
/// <exception cref="InvalidOperationException">The timestamp contains invalid values; either it is
/// incorrectly normalized or is outside the valid range.</exception>
public DateTimeOffset ToDateTimeOffset()
{
return new DateTimeOffset(ToDateTime(), TimeSpan.Zero);
}
/// <summary>
/// Converts the specified <see cref="DateTime"/> to a <see cref="Timestamp"/>.
/// </summary>
/// <param name="dateTime"></param>
/// <exception cref="ArgumentException">The <c>Kind</c> of <paramref name="dateTime"/> is not <c>DateTimeKind.Utc</c>.</exception>
/// <returns>The converted timestamp.</returns>
public static Timestamp FromDateTime(DateTime dateTime)
{
if (dateTime.Kind != DateTimeKind.Utc)
{
throw new ArgumentException("Conversion from DateTime to Timestamp requires the DateTime kind to be Utc", "dateTime");
}
// Do the arithmetic using DateTime.Ticks, which is always non-negative, making things simpler.
long secondsSinceBclEpoch = dateTime.Ticks / TimeSpan.TicksPerSecond;
int nanoseconds = (int) (dateTime.Ticks % TimeSpan.TicksPerSecond) * Duration.NanosecondsPerTick;
return new Timestamp { Seconds = secondsSinceBclEpoch - BclSecondsAtUnixEpoch, Nanos = nanoseconds };
}
/// <summary>
/// Converts the given <see cref="DateTimeOffset"/> to a <see cref="Timestamp"/>
/// </summary>
/// <remarks>The offset is taken into consideration when converting the value (so the same instant in time
/// is represented) but is not a separate part of the resulting value. In other words, there is no
/// roundtrip operation to retrieve the original <c>DateTimeOffset</c>.</remarks>
/// <param name="dateTimeOffset">The date and time (with UTC offset) to convert to a timestamp.</param>
/// <returns>The converted timestamp.</returns>
public static Timestamp FromDateTimeOffset(DateTimeOffset dateTimeOffset)
{
// We don't need to worry about this having negative ticks: DateTimeOffset is constrained to handleView on GitHub (pinned to 016f98412e)