NodaTime: Replicating DateTime.Today - c#

My service requests data from an external service that needs an argument for a particular date (doesn't need time information).
Until now, I've been using DateTime.Today (e.g. 10/24/2014 12:00:00).
I've moved to using NodaTime for improved testability but not sure of the best way to replicate this functionality:
public class SomeClass(IClock clock)
{
_clock = clock; //Injected at runtime, provides mockable interface
var localNow = _clock.Now.InZone(_serverTimeZone);
var today = localNow.ToDateTimeUnspecified().Date; //This close enough? Seems kinda long
}

To represent a date, you should use LocalDate rather than DateTime, ideally. So you want:
var localNow = clock.Now.InZone(serverZone);
var today = localNow.Date;
If you must use DateTime, then your current code is fine.
In Noda Time 2.0, this will be simpler due to a ZonedClock which is basically a composite of a clock and a time zone, allowing you to write:
// Or whatever...
private readonly ZonedClock zonedClock = clock.InZone(zone);
// Then later
LocalDate date = zonedClock.GetCurrentDate();
Noda Time 2.0 isn't ready for release yet, but I wanted to give you an idea of what's coming.

Related

Date Time Struct to deal with different time zones

I make struct name DateTimeZone , I set it to take the UTC time and I get it to take local time.
DateTimeZone time = DateTime.Now;//time will equal the UTC time
DateTime localTime= time; // local time will equal the Local time
the struct
public struct DateTimeZone
{
private DateTime dateTime;
// public DateTimeZone Value { get; }
public static implicit operator DateTimeZone(DateTime value)
{
return new DateTimeZone() { dateTime = value.ToUniversalTime() };
}
public static implicit operator DateTime(DateTimeZone value)
{
return value.dateTime.ToLocalTime();
}
}
My question : is there easiest way to implement this than struct?
and this struct have exception when i save in DB cause entity frame work,
so I need to make mapping every time I use struct , How I can make mapping in concise manner?
A few things:
Be careful with your naming. An object with a name like DateTimeZone would be expected to contain either 1) time zone information only, or 2) a date and time and time zone. Your object is only an encapsulation wrapper around DateTime, so it is neither of these things.
Implicit operations can be evil - especially if they change the meaning of the value you're working with. I don't recommend using them with date/time, unless you really know what you're doing. It will quickly become confusing to any user of this object as to what value you were actually working with.
The ToUniversalTime and ToLocalTime functions change their behavior based on the DateTimeKind assigned to the .Kind property of the DateTime objects you're working with. You seem to be creating an API in which DateTime is always local and DateTimeZone is always UTC, but DateTimeKind will get in the way of this idea.
As mentioned in comments, you might look into using Noda Time, which is a very solid and well-thought-out API. In Noda Time, the Instant type always represents UTC, and the LocalDateTime type always represents a timezoneless date and time. Time zones are represented by DateTimeZone (see the conflict with your name), and the ZonedDateTime type combines these, such that you have both instant-in-time information, local-time information, and the associated time zone.
You mentioned Entity Framework. Unfortunately, EF will not work directly with either your custom object, or with Noda Time. It does not have the ability to do simple type conversions. This has been requested, but not yet implemented. You can follow the work item for it here. A workaround you can use is "buddy properties", as described here. They're not fun, but they work. Mostly.
You may find it reasonable to just use DateTime, and call methods like ToUniversalTime or ToLocalTime manually, when needed. If you want EF to properly set DateTimeKind when loading from the database, see this answer.
Keep in mind that both ToUniversalTime and ToLocalTime work with the computer's local time zone where the code happens to be running. This works fine for desktop and mobile applications, but is rarely desired for web applications, because changing the time zone of the server could drastically affect the data. Consider instead working with a named time zone via the built-in TimeZoneInfo class, or with the DateTimeZone class in Noda Time.
Additional reading for you:
Daylight saving time and time zone best practices
The timezone tag wiki
Maybe you should try this one:
public struct DateTimeZone
{
public DateTime DateTime;
public static explicit operator DateTimeZone(DateTime dt)
{
return new DateTimeZone { DateTime = dt.ToUniversalTime() };
}
}
var time = (DateTimeZone)DateTime.Now;
var localTime = time.DateTime;

How to get precise DateTime in C#

I know that DateTime.UtcNow does not have a relatively high degree of precision (10-15 ms resolution).
This is a problem for me because in my log files, I want better resolution for the purposes of resolving race conditions.
The question is: how can I get the current date/time with a better precision than what DateTime.UtcNow offers?
The only solution which I've seen up till now has been this: https://stackoverflow.com/a/15008836/270348. Is that a suitable way to solve the problem?
You can use Stopwatch for more precise measurements of time. You can then have each log entry record the time from the start of the first operation. If it's important, you can record the DateTime of the first operation and therefore calculate the times of the rest, but it sounds like just having the ticks/nanoseconds since the start of the first operation is good enough for your purposes.
If you want to add tracing you could write your own ETW Trace Provider like here. Then you do not need to take care how the timing is fetched. The Windows Kernel will take care that the timing is accurate and the order of the events is correct.
If you do not want to write your own ETW Provider you can use EventSource which is available as Nuget Package which allows you to use it from .NET 4.0 as well. More infos has Vance Morrison on his blog.
When use ETW events then you get a powerful trace analyzer for free with the Windows Performance Toolkit. As added bonus you can do system wide profiling in all processes with minimal impact as well.
This allows you to selectively add call stacks for every event you write which can be invaluable when you want to track down who did call your Dispose method two times.
Do you really need a precise timer or what you really need is something that give a sort? For example:
static class AutoIncrement
{
private static long num;
public static long Current
{
get
{
return Interlocked.Increment(ref num);
}
}
}
Console.WriteLine(AutoIncrement.Current);
Console.WriteLine(AutoIncrement.Current);
Console.WriteLine(AutoIncrement.Current);
Console.WriteLine(AutoIncrement.Current);
Console.WriteLine(AutoIncrement.Current);
This is guaranteed to be unique, and to change every time, and to be sorted. Its precision is better than microsecond. Its precision is absolute on a single PC.
or if you really want Timestamps...
static class AutoIncrement
{
private static long lastDate;
public static DateTime Current
{
get
{
long lastDateOrig, lastDateNew;
do
{
lastDateOrig = lastDate;
lastDateNew = lastDateOrig + 1;
lastDateNew = Math.Max(DateTime.UtcNow.Ticks, lastDateNew);
}
while (Interlocked.CompareExchange(ref lastDate, lastDateNew, lastDateOrig) != lastDateOrig);
return new DateTime(lastDateNew, DateTimeKind.Utc);
}
}
}
DateTime ac = AutoIncrement.Current;
Console.WriteLine(CultureInfo.InvariantCulture, "{0} {1:yyyy/MM/dd HH:mm:ss.fffffff}", ac.Ticks, ac);
This last variant uses as a base DateTime.UtcNow, but each call if it isn't changed, it increments it by one.

ensure that utc datetime is persisted

Let us say I have a situation where I set the creation UTC date time just before I persist the entity. Usually, I would do it like this:
var something = new Something;
something.CreationDT = DateTime.UtcNow;
repo.Save(something);
What is the best way to ensure that this always happens. I know how to create a DateTime wrapper for testing purposes but this would not necessary help me here as programmers could still use:
something.CreationDT = DateTime.Now;
Is there a pattern to ensure that every programmer uses UTC?
If you always want to force the UTC date on the object and this is the exact code, then just do it as part of the constructor e.g.
public Something()
{
CreatedDT = DateTime.UtcNow;
}
public DateTime CreatedDT { get; private set; }
...
Save(new Something());
Obviously this doesn't cater for scenarios where you create the object earlier in the application and persist later, however, that doesn't appear to be the case here.
I would definitely avoid allowing users to set Now whilst internally returning UtcNow, that's just going to confuse people. If anything use UtcNow is better as it's more readable for the developer - it's clear to see that the value has to be UTC.
For this sort of thing, I generally try to let the DB do as much work as possible so I would have a default value set to the current UTC date/time so I don't need to worry about sending it from my client at all.

Instant.Now for NodaTime

I'm trying to get a handle on using the Noda Time framework by Jon Skeet (and others).
I'm trying to store the current now(Instant). Instant is created from a long ticks, but what is the current now count of Ticks?
Is it:
Instant now = new Instant(DateTime.Now.ToUniversalTime().Ticks);
And or?
Instant now = Instant.FromDateTimeUtc(DateTime.Now.ToUniversalTime());
Are they equivalent, am I even doing this right?
PS, if Jon answer's this - I'd like to propose an Instant.Now property.
PS2 I know the title contains a tag, but it wouldn't let me have a short "Instant.Now" title.
I did a bit of research and it seems that the NodaTime way is to get the now moment according to a clock.
If you want to get the current time using the system clock, just use SystemClock.Instance.GetCurrentInstant().
However, instead of using the SystemClock.Instance directly in your code, it's preferable that you inject an IClock dependency in your time-aware classes.
This will allow you to:
provide the class with SystemClock.Instance at runtime, so the code will use the correct time
supply a fake implementation of IClock during unit testing to allow you to tweak the time as needed in order to test various scenarios (like the passing of time). There's a NodaTime.Testing project that offers such a class, called FakeClock.
I find this very useful. I think having something like new Instant() or Instant.Now return the current time would make it easier to hardcode usages of SystemClock under the covers, therefore missing the testing advantage that NodaTime offers.
For more info on unit testing with NodaTime, see this link.
Regarding your code examples: they are not equivalent.
Instant.FromDateTimeUtc(DateTime.Now.ToUniversalTime()) will indeed give you the current instant in UTC.
new Instant(DateTime.Now.ToUniversalTime().Ticks) will give you a wrong date far in the future, because the BCL's DateTime.Ticks represents the number of ticks since 1/1/0001, and NodaTime's Instant.Ticks represents the number of ticks since 1/1/1970 (see the remark here).
SystemClock.Now returns the current time as an Instant value:
Instant now = SystemClock.Instance.Now;
But you may want to heed the remarks in the documentation for the IClock interface:
IClock is intended for use anywhere you need to have access to the current time. Although it's not strictly incorrect to call SystemClock.Instance.Now directly, in the same way as you might call UtcNow, it's strongly discouraged as a matter of style for production code. We recommend providing an instance of IClock to anything that needs it, which allows you to write tests using the stub clock in the NodaTime.Testing assembly (or your own implementation).
As a simple example, suppose you have a Logger class that needs the current time. Instead of accessing SystemClock directly, use an IClock instance that's supplied via its constructor:
public class Logger
{
private readonly IClock clock;
public Logger(IClock clock)
{
this.clock = clock;
}
public void Log(string message)
{
Instant timestamp = this.clock.Now;
// Now log the message with the timestamp...
}
}
When you instantiate a Logger in your production code, you can give it SystemClock.Instance. But in a unit test for the Logger class, you can give it a FakeClock.

Difficulty comparing two DateTime instances

I'm writing a Unit Test class in C# (.NET 4.5). In one of the tests I'm checking the values of various properties after an instance of our class FeedbackDao is constructed. On construction, the FeedbackDate property of FeedbackDao is set to DateTime.Now.
FeedbackDao feedbackDao = new FeedbackDao();
// a couple of lines go here then I set up this test:
Assert.IsTrue(feedbackDao.FeedbackDate.CompareTo(DateTime.Now) < 0);
My assumption is that feedbackDao.FeedbackDate should always be just a little earlier than the current time returned by DateTime.Now, even if it's only by a millisecond, and my IsTrue test should always pass, but sometimes it passes and sometimes it fails. When I add a message like this:
Assert.IsTrue(feedbackDao.FeedbackDate.CompareTo(DateTime.Now) < 0,
feedbackDao.FeedbackDate.CompareTo(DateTime.Now).ToString());
the message sometimes reads -1 (meaning that FeedbackDate is earlier than Now) and sometimes reads 0 (meaning that the DateTime instances are equal).
Why is FeedbackDate not always earlier than Now? And, if I can't trust that comparison, how can I write a rigorous test to check the value of FeedbackDate when FeedbackDao is constructed?
My assumption is that feedbackDao.FeebackDate should always be just a little earlier than the current time returned by DateTime.Now, even if it's only by a millisecond.
What makes you think that? That would suggest that 1000 calls would have to take at least 1 second which seems unlikely.
Add to that the fact that DateTime.Now only has a practical granularity of about 10-15ms IIRC, and very often if you call DateTime.Now twice in quick succession you'll get the same value twice.
For the purpose of testability - and clean expression of dependencies - I like to use a "clock" interface (IClock) which is always used to extract the current system time. You can then write a fake implementation to control time however you see fit.
Additionally, this assertion is flawed:
Assert.IsTrue(feedbackDao.FeebackDate.CompareTo(DateTime.Now) < 0,
feedbackDao.FeebackDate.CompareTo(DateTime.Now).ToString());
It's flawed because it evaluates DateTime.Now twice... so the value that it reports isn't necessarily the same one that it checks. It would be better as:
DateTime now = DateTime.Now;
Assert.IsTrue(feedbackDao.FeebackDate.CompareTo(now) < 0,
feedbackDao.FeebackDate.CompareTo(now).ToString());
Or even better:
DateTime now = DateTime.Now;
DateTime feedbackDate = feedbackDao.FeebackDate;
Assert.IsTrue(now < feedbackDate,
feedbackDate + " should be earlier than " + now);
Your test is not that useful as it is, you're asserting that the value is less than DateTime.Now but that does not mean it was correctly set to the expected value. If the date time is not initialized it will have the DateTime.MinValue and that value will always pass the test.
This test is as valid as testing for feedbackDao.FeebackDate.CompareTo(DateTime.Now) <= 0 and with that you would not have the problem that motivated you to write this question.
You need to extract the dependency on DateTime.Now or use a mocking framework that supports mocking DateTime.Now and assert that the value is initialized to the correct one. You can check Microsoft Moles, now renamed to Fakes in VS 2012, which is the only mocking framework that I know that is free (kind of for the latest version, since it ships with VS and don't know if it is available on the express editions) and that will let you replace a call to DateTime.Now.
Update:
Without resorting to a mocking framework you could improve your test by doing something like this:
var lowerBoundary = DateTime.Now;
var dao = new FeedbackDao();
var upperBoundary = DateTime.Now;
Assert.IsTrue(dao.Date >= lowerBoundary && dao.Date <= upperBoundary);
When unit testing, I consider DateTime.Now to be an external dependency, and thus something needing to be mocked. What I've done in the past when testing scenarios involving DateTime.Now, I've just passed a Func<DateTime> in via the constructor of the class, which allows me to mock DateTime.Now during testing.
I prefer this over Jon Skeet's suggestion of using something like an IClock interface to wrap around the DateTime properties, just because the last time I did this, I felt silly making a new interface and class to wrap around a single property. If you're going to need to test around more than one of the static DateTime properties, I definitely agree with the IClock suggestion.
For example,
public class Foo
{
private readonly Func<DateTime> timeStampProvider;
public Foo(Func<DateTime> timeStampProvider)
{
this.timeStampProvider = timeStampProvider;
}
public Foo() : this(() => DateTime.Now)
{
}
public bool CompareDate(DateTime comparisonDate)
{
// Get my timestamp
return comparisonDate > timeStampProvider();
}
}
Then, during testing,
var testFoo = new Foo(() => new DateTime(1, 1, 2010));
I generally use a mock data to validate my logic. I evolve my test scenarios around the mock data. As suggested by DBM.
Mock data is a set of known data that is generally static or configurable. Common practice is to have a XML file with all the test data and load them as and when required. I can give you an example in our Project.
Try
Assert.IsTrue(feedbackDao.FeebackDate.CompareTo(DateTime.Now) < 1);
Or
Assert.IsTrue(feedbackDao.FeebackDate - DateTime.Now < someMarginOfError);
Time is generally fairly granular - often 10's of milliseconds IIRC.
Depending on your system, DateTime.Now is not updated every millisecond or tick, it is only updated periodically. Typically 10 ms or so. See here: How frequent is DateTime.Now updated ? or is there a more precise API to get the current time?
DateTime.Now isn't 100% accurate. It increases by around 130 ms(from personal experience per tick). So it's verry likely that if your method is fast enough the date will be equal to datetime.now and not smaller.
If you want a 100% accurate timer you should use the StopWatch class.
Msdn link to stopwatch

Categories

Resources