i'm starting to build a part of a system which will hold a lot of DateTime validations, and a lot of 'if it was done before now' or 'if it will start in an hour etc'.
Usual way to go is to use DateTime.Now to get the actual time.
I predict however, that during unit test that will give me a real headache because i will have to setup my testdata for the time when the test will run in stead of use a default set of test data.
So i thought: why not use my own 'now' so i can set the current datetime to any moment in time.
As i don't want to set the testservers internal clock i was thinking about this solution, and i was wondering what you think of it.
Base thought is that i use my own DateTime class.
That class gives you the current datetime, but you can also set your own time from outside.
public static class MyDateTime
{
private static TimeSpan _TimeDifference = TimeSpan.Zero;
public static DateTime Now
{
get
{
return DateTime.Now + _TimeDifference;
}
}
public static void SetNewNow(DateTime newNow)
{
_TimeDifference = newNow - DateTime.Now;
}
public static void AddToRealTime(TimeSpan timeSpan )
{
_TimeDifference = timeSpan;
}
public static void SubtractFromRealTime(TimeSpan timeSpan)
{
_TimeDifference = - timeSpan;
}
}
Some time ago i already read something about it. A short search for mock DateTime.Now with your favorite search engine should reveal enough links.
This seems to look quite interesting:
http://blog.typemock.com/2009/05/mockingfaking-datetimenow-in-unit-tests.html
what do u mean ?
if u need any specialization, so u can use Extension methods !
easily write an extension method for DateTime class and do whatever u need.
Related
I have following time samples:
06:09
08:10
23:12
00:06 // next day
00:52
I have a sample 00:31 (nextday) that needs to be compared and check if its less then the above samples.
if (cdnTime > nextNode)
{
//dosomething
}
cdnTime here is the 00:31 and nextNode is the above given multiple samples. Time 00:31 is greater then all samples except 00:52 so I need the if statement to be false until it reaches 00:52. How do I achieve this. Keeping in mind the time samples switch to next day, do I need to make it as DateTime and then compare or is there any way of comparison with TimeSpan without dates.
Yes you need to somehow tell that it's another day. You can either use a DateTime, but you could also initialize a timespan with an additional day - it provides a Parse-method for this:
using System;
using System.Globalization;
public class Program
{
public static void Main()
{
var cdnTime = TimeSpan.Parse("23:12", CultureInfo.InvariantCulture);
var nextTime = TimeSpan.Parse("01.00:03", CultureInfo.InvariantCulture);
Console.WriteLine(cdnTime.TotalMinutes);
Console.WriteLine(nextTime.TotalMinutes);
Console.WriteLine(cdnTime.CompareTo(nextTime));
Console.WriteLine(cdnTime < nextTime);
}
}
Another option would be to add the day afterwards:
var anotherTime = TimeSpan.FromMinutes(3);
anotherTime = anotherTime.Add(TimeSpan.FromDays(1));
Console.WriteLine(anotherTime.TotalMinutes);
You can try it out here:
https://dotnetfiddle.net/k39TIe
I want to query the update timestamp _ts on documents to get documents that haven't mutated since a certain amount of time.
When I create a select query in the azure portal this works:
SELECT TOP 10 c.id FROM c WHERE c._ts < 6.35909919217878E+17
The wierd number is the Ticks created with a datetime object, see below.
But when I try to create it through LINQ it won't do because you don't have _ts but a Timestamp as a DateTime object. When I try to enter a full DateTime object to compare to the Timestamp it crashes saying it doesn't support it. So I try this:
DocRepo.Get(x => x.Timestamp.Ticks < CloseDate.Ticks);
This results to nothing and when I watch the query executed it has this as a select query:
SELECT * FROM root WHERE root[\"_ts\"][\"Ticks\"] < 6.35909943137688E+17
Is it possible to query on the _ts timestamp or do i have to have an extra updatedAt field to do it, which seems redundant.
You have a couple of problems with your queries. In your first query, you are comparing "Ticks" (one ten millionth of a second - see here) to the _ts value which will most likely return all the documents in your collection because the _ts value is a POSIX (Unix) time measured in seconds see here. They also aren't based on the same epoch. The Unix value starts at midnight 1,1,1970 where the Ticks start at midnight 1,1,0001 Therefore, the _ts value will always be much smaller than the Ticks value (not to mention off by 1,969 years!). You will need to convert your dates to their Unix time value. You could create an Extension method to help you do this:
public static long ToUnixTime(this DateTime date)
{
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return (long)(date - epoch).TotalSeconds;
}
As for the Linq statement, you can't (unfortunately) put a DateTime into a Linq query because a DateTime value won't convert to a const (which is the error you are getting). So, in both cases, you can't compare either the _ts value or TimeStamp value very easily.
So what to do? Well, in looking at the DocumentDB SDK, if you look at the definition of TimeStamp you will see the following:
// Summary:
// Gets the last modified timestamp associated with the resource.
[JsonConverter(typeof(UnixDateTimeConverter))]
[JsonProperty(PropertyName = "_ts")]
public virtual DateTime Timestamp { get; internal set; }
So by default, the SDK is converting the _ts value to a DateTime and exposing it through TimeStamp field. There are a couple of things you could do depending on what type your DocRepo is returning. If it is the default Document type, you could create a new class and inherit from the Docment type like this:
public class MyDocument : Document
{
public long _ts
{
get; set;
}
}
If it is your own custom class, then just add the _ts field to your class. Either way, if the _ts field is present, DocumentDB will populate the field. Then, if you add the ToUnixTime extension method you could compose your Linq query like this:
DocRepo.Get(x => x._ts < CloseDate.ToUnixTime());
It may not be an elegant solution and someone (hopefully) might come up with a better solution, but I have verified that it works against my own DocumentDB collection.
Hope this helps.
This is what i use to convert Unix timestamp into DateTime format we can easily understand in C#:
public DateTime TimeStamp
{
get
{
return DateTimeOffset.FromUnixTimeSeconds(int.Parse(_ts)).DateTime;
}
}
Hope this helps.
I have a view model in which I am storing a DateTime but in my view using a JQUERY datetimepicker, time only:
ViewModel
[DataType(DataType.Time)]
public DateTime? MondayFrom { get; set; }
[DataType(DataType.Time)]
public DateTime? MondayTo { get; set; }
As it stands, when the Create method gets called it is using todays date plus the time selected from the timepicker.
As I am not particularly concerned with the Date part of the DateTime, I want to change the day, month & year to 01/01/1900 or something less specific than the date the record was written, before the record is created, this is purely to avoid any confusion in the future.
I don't want to get bogged down on whether this is the right thing to do or not.
I'm struggling to get a handle on the Date part of the DateTime, see below:
public void CreateClub(Club club)
{
foreach (var item in club.MeetingDays)
{
// change Date part to 01/01/1900, leave the time as is..
}
_repository.CreateClub(club);
}
How might I floor the date part of the item but leave the time well alone?
Just use the TimeOfDay property to extract the time within the day, and add that to the date you want:
private static readonly DateTime BaseDate = new DateTime(1900, 1, 1);
var updatedDateTime = BaseDate + otherDateTime.TimeOfDay;
You could even write an extension method or two:
public static DateTime WithDate(this DateTime start, DateTime date)
{
// No need to use the Date property if you already know
// it will be midnight...
return date.Date + start.TimeOfDay;
}
public static DateTime WithFloorDate(this DateTime start)
{
return start.WithDate(FloorDate);
}
Of course, I'd suggest you use Noda Time where you can specify dates, times and date/time values (with or without a time zone or UTC offset0 separately, but that's a different conversation.
DateTime is immutable - you cant just change part of it. You can extract the time and add it to a "base" date:
for(int i=0; i < club.MeetingDays.Count; i++)
{
club.MeetingDays[i] = new DateTime(1900, 1, 1) + club.MeetingDays[i].TimeOfDay;
}
Note that you need a for loop so you can place the new value back in the collection. You could also use Linq:
club.MeetingDays = club.MeetingDays
.Select(t => new DateTime(1900, 1, 1) + t.TimeOfDay)
.ToList();
Assuming that club.MeetingDays is a List<Datetime>
I use many DateTime in my code. I want to change those DateTimes to my specific date and keep
time.
1. "2012/02/02 06:00:00" => "2015/12/12 : 06:00:00"
2. "2013/02/02 12:00:00" => "2015/12/12 : 12:00:00"
I use this style to change, but it seem not the good way and I want to ask have any way to achieve this task.
DateTime newDateTime = new DateTime(2015,12,12,oldDateTime.Hour,oldDateTime.Minute,0);
A better way that preserves the seconds, milliseconds and smaller parts of the time would be:
DateTime newDateTime = new DateTime(2015,12,12) + oldDateTime.TimeOfDay;
Or you could make an extension method to apply a new Date to an existing DateTime and, at the same time, not trust the new date to be without a TimeOfDay on it:-
public static DateTime WithDate (this DateTime datetime, DateTime newDate)
{
return newDate.Date + datetime.TimeOfDay;
}
IMHO DateTime is one of the weakest parts of .NET. For example, a TimeSpan is not the same as a TimeOfDay nor can it represent a 'TimePeriod' (in months) - these are three separate concepts and mixing them up was a poor choice. Moving to DateTimeOffset is generally preferred or to the excellent Noda time library.
With the information you have given, I think this method is fine. If you want to avoid rewriting the oldDateTime.Hour,oldDateTime.Minute,0 piece often, you could create your own static class to simplify the method calls.
In your regular application:
class Program
{
static void Main(string[] args)
{
DateTime time = DateTime.Now;
DateTime newDateTime = MyDateTimeUtil.CreateDateFromTime(2015, 12, 12, time);
}
}
The static class that creates the DateTime value:
public static class MyDateTimeUtil
{
public static DateTime CreateDateFromTime(int year, int month, int day, DateTime time)
{
return new DateTime(year, month, day, time.Hour, time.Minute, 0);
}
}
We're writing a dll that can be accessed by other teams. One of our requirements is that every DateTime passed has a DateTimeKind.Utc.
However, we're not enforcing this requirement which leads to errors. So we were wondering how we can enforce this.
We had a few ideas:
Write an aspect that checks each parameter passed to a method. Throw an exception when the Kind != UTC. This works but does not work when you pass an object that contains a DateTime.
Change all our DateTimes with a custom object, UtcDateTime.
This might work but would need to make sure that we replace every DateTime and all calls to our datetimes. Would look something like this:
public class UtcDateTime
{
private DateTime _dateTime;
public UtcDateTime(DateTime dateTime)
{
if(dateTime.Kind != DateTimeKind.Utc)
{
throw new ArgumentException();
}
_dateTime = dateTime;
}
}
Any better ways to do this?
Change all our DateTimes with a custom object, UtcDateTime.
If you want to go that way and replace DateTime with something else, you might as well use DateTimeOffset, which includes time zone information.
You could use code contracts to enforce this.
Read about them here.
http://msdn.microsoft.com/en-us/library/dd264808(v=vs.110).aspx
As an example, you could use
Contract.Requires(yourDateTime.Kind == DateTime.Utc);
Alternatively, you could enforce the conversion in your method. If it is DateTimeKind.Unspecified, throw.
void Foo(ObjectWithDateTime foo)
{
if (foo.Date.Kind == DateTimeKind.Unspecified) {
throw ....
}
// convert here.
}