diff --git a/GitCommands/DateTimeUtils.cs b/GitCommands/DateTimeUtils.cs
index 78706b990b4..16da6c00d13 100644
--- a/GitCommands/DateTimeUtils.cs
+++ b/GitCommands/DateTimeUtils.cs
@@ -7,11 +7,26 @@ public static class DateTimeUtils
///
/// Midnight 1 January 1970.
///
- public static readonly DateTime UnixEpoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ private static readonly DateTime UnixEpoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ ///
+ /// Parse unix time string
+ ///
+ /// Unix time string
+ /// DateTime (local time)
public static DateTime ParseUnixTime(string unixTime)
{
return UnixEpoch.AddSeconds(long.Parse(unixTime)).ToLocalTime();
}
+
+ ///
+ /// Convert from DateTime to native Git time format (unix time)
+ ///
+ /// DateTime
+ /// Unix time (seconds since 1970)
+ public static long ToUnixTime(DateTime dateTime)
+ {
+ return (long)(dateTime.ToUniversalTime() - UnixEpoch).TotalSeconds;
+ }
}
}
diff --git a/GitCommands/Git/GitModule.cs b/GitCommands/Git/GitModule.cs
index e14251259ae..41d326550b2 100644
--- a/GitCommands/Git/GitModule.cs
+++ b/GitCommands/Git/GitModule.cs
@@ -938,8 +938,8 @@ public GitRevision GetRevision(ObjectId? objectId = null, bool shortFormat = fal
AuthorEmail = ReEncodeStringFromLossless(lines[4]),
Committer = ReEncodeStringFromLossless(lines[6]),
CommitterEmail = ReEncodeStringFromLossless(lines[7]),
- AuthorDate = DateTimeUtils.ParseUnixTime(lines[5]),
- CommitDate = DateTimeUtils.ParseUnixTime(lines[8]),
+ AuthorUnixTime = long.Parse(lines[5]),
+ CommitUnixTime = long.Parse(lines[8]),
MessageEncoding = lines[9]
};
diff --git a/GitCommands/RevisionReader.cs b/GitCommands/RevisionReader.cs
index ede2a392f3d..793ebcd2902 100644
--- a/GitCommands/RevisionReader.cs
+++ b/GitCommands/RevisionReader.cs
@@ -117,6 +117,7 @@ private async Task ExecuteAsync(
// This property is relatively expensive to call for every revision, so
// cache it for the duration of the loop.
var logOutputEncoding = module.LogOutputEncoding;
+ long sixMonths = new DateTimeOffset(DateTime.Now.ToUniversalTime() - TimeSpan.FromDays(30 * 6)).ToUnixTimeSeconds();
using (var process = module.GitCommandRunner.RunDetached(arguments, redirectOutput: true, outputEncoding: GitModule.LosslessEncoding))
{
@@ -141,7 +142,7 @@ private async Task ExecuteAsync(
// We keep full multiline message bodies within the last six months.
// Commits earlier than that have their properties set to null and the
// memory will be GCd.
- if (DateTime.Now - revision.AuthorDate > TimeSpan.FromDays(30 * 6))
+ if (sixMonths > revision.AuthorUnixTime)
{
revision.Body = null;
}
@@ -340,10 +341,10 @@ int CountParents(int baseOffset)
#region Timestamps
// Lines 2 and 3 are timestamps, as decimal ASCII seconds since the unix epoch, each terminated by `\n`
- var authorDate = ParseUnixDateTime();
- var commitDate = ParseUnixDateTime();
+ var authorUnixTime = ParseUnixDateTime();
+ var commitUnixTime = ParseUnixDateTime();
- DateTime ParseUnixDateTime()
+ long ParseUnixDateTime()
{
long unixTime = 0;
@@ -353,7 +354,7 @@ DateTime ParseUnixDateTime()
if (c == '\n')
{
- return DateTimeUtils.UnixEpoch.AddTicks(unixTime * TimeSpan.TicksPerSecond).ToLocalTime();
+ return unixTime;
}
unixTime = (unixTime * 10) + (c - '0');
@@ -435,10 +436,10 @@ DateTime ParseUnixDateTime()
TreeGuid = treeId,
Author = author,
AuthorEmail = authorEmail,
- AuthorDate = authorDate,
+ AuthorUnixTime = authorUnixTime,
Committer = committer,
CommitterEmail = committerEmail,
- CommitDate = commitDate,
+ CommitUnixTime = commitUnixTime,
MessageEncoding = encodingName,
Subject = subject,
Body = body,
diff --git a/GitUI/UserControls/RevisionGrid/RevisionGridControl.cs b/GitUI/UserControls/RevisionGrid/RevisionGridControl.cs
index bc45082933e..e8726edda9b 100644
--- a/GitUI/UserControls/RevisionGrid/RevisionGridControl.cs
+++ b/GitUI/UserControls/RevisionGrid/RevisionGridControl.cs
@@ -1046,10 +1046,10 @@ void AddArtificialRevisions(ObjectId filteredCurrentCheckout)
GitRevision workTreeRev = new(ObjectId.WorkTreeId)
{
Author = userName,
- AuthorDate = DateTime.MaxValue,
+ AuthorUnixTime = 0,
AuthorEmail = userEmail,
Committer = userName,
- CommitDate = DateTime.MaxValue,
+ CommitUnixTime = 0,
CommitterEmail = userEmail,
Subject = ResourceManager.TranslatedStrings.Workspace,
ParentIds = new[] { ObjectId.IndexId },
@@ -1061,10 +1061,10 @@ void AddArtificialRevisions(ObjectId filteredCurrentCheckout)
GitRevision indexRev = new(ObjectId.IndexId)
{
Author = userName,
- AuthorDate = DateTime.MaxValue,
+ AuthorUnixTime = 0,
AuthorEmail = userEmail,
Committer = userName,
- CommitDate = DateTime.MaxValue,
+ CommitUnixTime = 0,
CommitterEmail = userEmail,
Subject = ResourceManager.TranslatedStrings.Index,
ParentIds = new[] { filteredCurrentCheckout },
diff --git a/IntegrationTests/UI.IntegrationTests/UserControls/RevisionGrid/CopyContextMenuItemTests.cs b/IntegrationTests/UI.IntegrationTests/UserControls/RevisionGrid/CopyContextMenuItemTests.cs
index 4f76c15bd4b..781cc91fefd 100644
--- a/IntegrationTests/UI.IntegrationTests/UserControls/RevisionGrid/CopyContextMenuItemTests.cs
+++ b/IntegrationTests/UI.IntegrationTests/UserControls/RevisionGrid/CopyContextMenuItemTests.cs
@@ -159,7 +159,7 @@ public void Should_should_show_info_for_multiple_commits()
{
Author = "Author1",
AuthorEmail = "author1@foo.bla",
- AuthorDate = new DateTime(2018, 10, 23, 11, 34, 21),
+ AuthorUnixTime = DateTimeUtils.ToUnixTime(new DateTime(2018, 10, 23, 11, 34, 21)),
};
GitRevision rev2 = new(ObjectId.Random())
{
@@ -167,7 +167,7 @@ public void Should_should_show_info_for_multiple_commits()
AuthorEmail = "author2@foo.bla",
Committer = "Committer2",
CommitterEmail = "committer2@foo.bar",
- CommitDate = new DateTime(2018, 10, 23, 11, 34, 21),
+ CommitUnixTime = DateTimeUtils.ToUnixTime(new DateTime(2018, 10, 23, 11, 34, 21)),
};
GitRevision rev3 = new(ObjectId.Random())
{
diff --git a/Plugins/GitUIPluginInterfaces/GitRevision.cs b/Plugins/GitUIPluginInterfaces/GitRevision.cs
index 870caea5022..7fa84cb6e80 100644
--- a/Plugins/GitUIPluginInterfaces/GitRevision.cs
+++ b/Plugins/GitUIPluginInterfaces/GitRevision.cs
@@ -51,10 +51,17 @@ public GitRevision(ObjectId objectId)
public string? Author { get; set; }
public string? AuthorEmail { get; set; }
- public DateTime AuthorDate { get; set; }
+
+ // Git native datetime format
+ public long AuthorUnixTime { get; set; }
+ public DateTime AuthorDate => FromUnixTimeSeconds(AuthorUnixTime);
public string? Committer { get; set; }
public string? CommitterEmail { get; set; }
- public DateTime CommitDate { get; set; }
+ public long CommitUnixTime { get; set; }
+ public DateTime CommitDate => FromUnixTimeSeconds(CommitUnixTime);
+
+ private static DateTime FromUnixTimeSeconds(long unixTime)
+ => unixTime == 0 ? DateTime.MaxValue : DateTimeOffset.FromUnixTimeSeconds(unixTime).LocalDateTime;
public BuildInfo? BuildStatus
{
diff --git a/UnitTests/GitUI.Tests/UserControls/RevisionGrid/Graph/LaneInfoProviderTests.cs b/UnitTests/GitUI.Tests/UserControls/RevisionGrid/Graph/LaneInfoProviderTests.cs
index 66bffcdae90..04016c40553 100644
--- a/UnitTests/GitUI.Tests/UserControls/RevisionGrid/Graph/LaneInfoProviderTests.cs
+++ b/UnitTests/GitUI.Tests/UserControls/RevisionGrid/Graph/LaneInfoProviderTests.cs
@@ -101,7 +101,7 @@ public void Setup()
GitRevision = new GitRevision(ObjectId.WorkTreeId)
{
Author = "John Doe",
- AuthorDate = DateTime.Parse("2010-03-24 13:37:12"),
+ AuthorUnixTime = DateTimeUtils.ToUnixTime(DateTime.Parse("2010-03-24 13:37:12")),
AuthorEmail = "j.doe@some.email.dotcom",
Body = "WIP: fixing bugs"
}
@@ -112,7 +112,7 @@ public void Setup()
GitRevision = new GitRevision(realCommitObjectId)
{
Author = "John Doe",
- AuthorDate = DateTime.Parse("2010-03-24 13:37:12"),
+ AuthorUnixTime = DateTimeUtils.ToUnixTime(DateTime.Parse("2010-03-24 13:37:12")),
AuthorEmail = "j.doe@some.email.dotcom",
Subject = "fix: bugs",
Body = "fix: bugs\r\n\r\nall bugs fixed"
@@ -124,7 +124,7 @@ public void Setup()
GitRevision = new GitRevision(mergeCommitObjectId)
{
Author = "John Doe",
- AuthorDate = DateTime.Parse("2010-03-24 13:37:12"),
+ AuthorUnixTime = DateTimeUtils.ToUnixTime(DateTime.Parse("2010-03-24 13:37:12")),
AuthorEmail = "j.doe@some.email.dotcom",
Subject = "merge remote tracking branch upstream/branch",
Body = "merge commit's subject here will not be parsed\r\n\r\nmerge commit's body might list details and/or conflicts...",
@@ -137,7 +137,7 @@ public void Setup()
GitRevision = new GitRevision(undetectedMergeCommitObjectId)
{
Author = "John Doe",
- AuthorDate = DateTime.Parse("2010-03-24 13:37:12"),
+ AuthorUnixTime = DateTimeUtils.ToUnixTime(DateTime.Parse("2010-03-24 13:37:12")),
AuthorEmail = "j.doe@some.email.dotcom",
Subject = "special merge",
Body = "merge commit's subject here will not be parsed\r\n\r\nmerge commit's body might list details and/or conflicts...",
@@ -150,7 +150,7 @@ public void Setup()
GitRevision = new GitRevision(innerCommitObjectId)
{
Author = "John Doe",
- AuthorDate = DateTime.Parse("2010-03-24 13:37:12"),
+ AuthorUnixTime = DateTimeUtils.ToUnixTime(DateTime.Parse("2010-03-24 13:37:12")),
AuthorEmail = "j.doe@some.email.dotcom",
Subject = "fix: further bugs",
Body = "fix: further bugs"