-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9ec4883
commit 97406d5
Showing
12 changed files
with
170 additions
and
13 deletions.
There are no files selected for viewing
9 changes: 9 additions & 0 deletions
9
DotNetThoughts.LocalTimeKit/DotNetThoughts.LocalTimeKit.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<Version>1.0.0</Version> | ||
<GenerateDocumentationFile>True</GenerateDocumentationFile> | ||
<PackageLicenseExpression>MIT</PackageLicenseExpression> | ||
</PropertyGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
@page "/timer" | ||
@using DotNetThoughts.LocalTimeKit | ||
|
||
<PageTitle>Timing</PageTitle> | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
TimeKeeping/DotNetThoughts.TimeKeeping.Tests/DotNetThoughts.TimeKeeping.Tests.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 3 additions & 1 deletion
4
TimeKeeping/DotNetThoughts.TimeKeeping.Tests/LocalDateTimeTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
TimeKeeping/DotNetThoughts.TimeKeeping/DotNetThoughts.TimeKeeping.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
138 changes: 138 additions & 0 deletions
138
TimeKeeping/DotNetThoughts.TimeKeeping/TimeTravelersClock.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
namespace DotNetThoughts.TimeKeeping; | ||
|
||
public class TimeTravelersClock | ||
{ | ||
public DateTimeOffset? FreezedAt { get; set; } | ||
public DateTimeOffset? Frozen { get; set; } | ||
public TimeSpan Offset { get; set; } = TimeSpan.Zero; | ||
|
||
public bool IsFrozen() | ||
{ | ||
using var context = new OperationContext(); | ||
return FreezedAt != null; | ||
} | ||
|
||
public DateTimeOffset Reset() | ||
{ | ||
using var context = new OperationContext(); | ||
Frozen = null; | ||
FreezedAt = null; | ||
Offset = TimeSpan.Zero; | ||
return UtcNow(); | ||
} | ||
|
||
public DateTimeOffset Thaw() | ||
{ | ||
using var context = new OperationContext(); | ||
if (FreezedAt == null) | ||
{ | ||
throw new InvalidOperationException("Cannot thaw when not frozen"); | ||
} | ||
Offset = Offset.Add(-RealTimeFrozen()); | ||
FreezedAt = null; | ||
Frozen = null; | ||
return UtcNow(); | ||
} | ||
|
||
public DateTimeOffset Freeze() | ||
{ | ||
using var context = new OperationContext(); | ||
FreezedAt = context.UtcNow(); | ||
Frozen = UtcNow(); | ||
return Frozen.Value; | ||
} | ||
|
||
public DateTimeOffset Freeze(DateTimeOffset baseLine) | ||
{ | ||
using var context = new OperationContext(); | ||
Reset(); | ||
SetBaseline(baseLine); | ||
FreezedAt = context.UtcNow(); | ||
Frozen = UtcNow(); | ||
return Frozen.Value; | ||
} | ||
|
||
public DateTimeOffset UtcNow() | ||
{ | ||
using var context = new OperationContext(); | ||
return Frozen ?? context.UtcNow().Add(Offset); | ||
} | ||
|
||
public DateTimeOffset AdvanceDays(double days) | ||
{ | ||
using var context = new OperationContext(); | ||
return Advance(TimeSpan.FromDays(days)); | ||
} | ||
|
||
public DateTimeOffset Advance(TimeSpan timeSpan) | ||
{ | ||
using var context = new OperationContext(); | ||
Offset = Offset.Add(timeSpan); | ||
if (IsFrozen()) | ||
{ | ||
Frozen = Frozen!.Value.Add(timeSpan); | ||
} | ||
return UtcNow(); | ||
} | ||
|
||
public DateTimeOffset SetBaseline(DateTimeOffset baseLine) | ||
{ | ||
if (IsFrozen()) throw new InvalidOperationException(); | ||
using var context = new OperationContext(); | ||
Offset = baseLine - context.UtcNow(); | ||
return UtcNow(); | ||
} | ||
|
||
public DateTimeOffset SetOffset(TimeSpan offset) | ||
{ | ||
if (IsFrozen()) throw new InvalidOperationException(); | ||
using var context = new OperationContext(); | ||
Offset = offset; | ||
|
||
return UtcNow(); | ||
} | ||
|
||
private TimeSpan RealTimeFrozen() | ||
{ | ||
using var context = new OperationContext(); | ||
return FreezedAt != null ? context.UtcNow() - FreezedAt.Value : TimeSpan.Zero; | ||
} | ||
|
||
internal void From(TimeTravelersClock xSystemTime) | ||
{ | ||
using var context = new OperationContext(); | ||
Offset = xSystemTime.Offset; | ||
FreezedAt = xSystemTime.FreezedAt; | ||
Frozen = xSystemTime.Frozen; | ||
} | ||
|
||
internal bool IsManipulated() | ||
{ | ||
return Offset != TimeSpan.Zero || FreezedAt != null; | ||
} | ||
|
||
internal class OperationContext : IDisposable | ||
{ | ||
private static AsyncLocal<DateTimeOffset?> _operationNow = new AsyncLocal<DateTimeOffset?>(); | ||
|
||
private bool _shouldReset = false; | ||
|
||
public OperationContext() | ||
{ | ||
if (_operationNow.Value == null) | ||
{ | ||
_operationNow.Value = DateTimeOffset.UtcNow; | ||
_shouldReset = true; | ||
} | ||
} | ||
public void Dispose() | ||
{ | ||
if (_shouldReset) | ||
{ | ||
_operationNow.Value = null; | ||
} | ||
} | ||
|
||
public DateTimeOffset UtcNow() => _operationNow.Value!.Value; | ||
} | ||
} |