peass-ng/PEASS-ng · error · ArgumentException
DateTime value may not be before the epoch
Error message
DateTime value may not be before the epoch
What it means
DateTimeUtilities.DateTimeToUnixMs converts a DateTime to whole milliseconds since the Unix epoch (1 Jan 1970 UTC). It throws ArgumentException with the message 'DateTime value may not be before the epoch' when the input compares earlier than UnixEpoch, because a negative result cannot be represented as a valid 'whole milliseconds after epoch' per the API contract (used e.g. in OCSP/TSP timestamp math).
Source
Thrown at winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/util/date/DateTimeUtilities.cs:23
public class DateTimeUtilities
{
public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1);
private DateTimeUtilities()
{
}
/// <summary>
/// Return the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC) for a given DateTime value.
/// </summary>
/// <param name="dateTime">A UTC DateTime value not before epoch.</param>
/// <returns>Number of whole milliseconds after epoch.</returns>
/// <exception cref="ArgumentException">'dateTime' is before epoch.</exception>
public static long DateTimeToUnixMs(
DateTime dateTime)
{
if (dateTime.CompareTo(UnixEpoch) < 0)
throw new ArgumentException("DateTime value may not be before the epoch", "dateTime");
return (dateTime.Ticks - UnixEpoch.Ticks) / TimeSpan.TicksPerMillisecond;
}
/// <summary>
/// Create a DateTime value from the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC).
/// </summary>
/// <param name="unixMs">Number of milliseconds since the epoch.</param>
/// <returns>A UTC DateTime value</returns>
public static DateTime UnixMsToDateTime(
long unixMs)
{
return new DateTime(unixMs * TimeSpan.TicksPerMillisecond + UnixEpoch.Ticks);
}
/// <summary>
/// Return the current number of milliseconds since the Unix epoch (1 Jan., 1970 UTC).
/// </summary>View on GitHub (pinned to 53fb989abc)
Solutions
- Validate the input before calling: reject or clamp any dateTime earlier than new DateTime(1970,1,1) (BouncyCastle's UnixEpoch) to zero or to the epoch itself.
- Fix the data source so uninitialized/missing dates are not passed through (use nullable DateTime or a sentinel check).
- Check DateTimeKind and normalize to UTC before comparing, since a Kind mismatch can push a valid boundary value below the epoch.
- Catch ArgumentException around DateTimeToUnixMs and fall back to epoch (0 ms) or surface a user-facing validation error.
Example fix
// before long ms = DateTimeUtilities.DateTimeToUnixMs(record.CreatedAt); // record.CreatedAt may be default(DateTime) // after var epoch = new DateTime(1970, 1, 1); var dt = record.CreatedAt == default ? epoch : record.CreatedAt.ToUniversalTime(); if (dt < epoch) dt = epoch; long ms = DateTimeUtilities.DateTimeToUnixMs(dt);
Defensive patterns
Strategy: validation
Validate before calling
private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
if (dateTime == default || dateTime < UnixEpoch)
dateTime = UnixEpoch; // clamp, or reject with your own validation error
long ms = Org.BouncyCastle.Utilities.Date.DateTimeUtilities.DateTimeToUnixMs(dateTime.ToUniversalTime()); Type guard
static bool IsAfterEpoch(DateTime dt)
{
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return dt != default && dt.ToUniversalTime().CompareTo(epoch) >= 0;
} Try / catch
try
{
long ms = DateTimeUtilities.DateTimeToUnixMs(dateTime);
}
catch (ArgumentException ex) when (ex.Message.Contains("before the epoch"))
{
long ms = 0; // or log and surface a validation error
} Prevention
- Normalize all dates to UTC and validate >= 1970-01-01 before timestamp math.
- Never pass default(DateTime) or DateTime.MinValue into epoch conversions.
- Use DateTime? (nullable) to distinguish missing dates from real values.
- Check DateTimeKind and call ToUniversalTime() to avoid boundary shifts.
- Add boundary unit tests for dates at and just before the epoch.
When it happens
Trigger: Passing a DateTime with CompareTo(UnixEpoch) < 0 to DateTimeToUnixMs — i.e. any date before 1970-01-01 00:00:00 UTC, including DateTime.MinValue, zero-initialized DateTime fields, or default(DateTime) (0001-01-01).
Common situations: Uninitialized/default DateTime structs flowing into certificate/timestamp validation code; parsing legacy dates stored as 0 or negative values; timezone conversion mistakes that shift a value near the epoch boundary below the epoch; deserializing missing date fields as DateTime.MinValue.
Related errors
- Resources.InvalidDriveLetterArgument
- Resources.InvalidDriveLetterArgument
- path
- Resources.Unsupported_Path_Format
- Resources.Cannot_Create_Directory
AI-assisted analysis of peass-ng/PEASS-ng@53fb989abc (2026-09-02).
Data as JSON: /api/errors/177ecdc957dda4b0.
Report an issue: GitHub.