I have written a simple test method to verify a method that converts a long value to DateTime, following is the code...
[TestMethod]
public void ConvertToDateTime_TestMethod()
{
long date = 1500024370374;
DateTime result = date.GetDateTime();
DateTime comparisonDate = new DateTime(2017, 07, 14, 9, 26, 10);
Assert.AreEqual(result, comparisonDate);
}
Point is that both date and time values are exactly same (also verified in watch window) why does it gives this exception? I found this article that uses a delta to compare if minor time difference is failing the comparison but still unsure why I still need an extra function to compare date/time assertions.
Edit-1: Here is my date conversion method which I am testing
public static DateTime GetDateTime(this long milliseconds)
{
try
{
return new DateTime(1970, 1, 1).AddMilliseconds(Convert.ToDouble(milliseconds));
}
catch { throw; }
}
Even though there is an alternate to this with new datetime(long), but logically whats wrong with this?
To the nearest second (the granularity the console is showing you) they are equal. To the nearest millisecond, they are not
long date = 1500024370374;
DateTime result = new DateTime(1970,1,1).AddMilliseconds(date);
DateTime comparisonDate = new DateTime(2017, 07, 14, 9, 26, 10);
Console.WriteLine(result.ToString("dd-MM-yyyy HH:mm:ss.fffff"));
// 14-07-2017 09:26:10.37400
Console.WriteLine(comparisonDate.ToString("dd-MM-yyyy HH:mm:ss.fffff"));
// 14-07-2017 09:26:10.00000
Live example: http://rextester.com/PYDLAD6594
Related
So i need to return a variable that checks whether the date the user inputs falls between the 2 dates I given. For now I didn't do the user part.
I tried checking and returning a variable but the above error is given
public bool IsInPeakSeason(DateTime date)
{
DateTime date1 = new DateTime(2019, 06, 15);
DateTime date2 = new DateTime(2019, 08, 15);
DateTime dateCheck >= date1 && dateCheck <date;
return date >= date1 && date < date2;
}
I want to return either true or false if the date is either in between or not between the given dates
The error you're getting is that you're attempting to use dateCheck in it's initial assignment, which is not allowed. In otherwords, you can't do something like int number = number + 1; because number on the right hand side of the assignment is not assigned yet. Of course the line in question must have some other typos in it, because it won't compile at all.
Regardless, you don't really need that line anyway (the variable isn't used anywhere else). If you remove it, your code should work as expected.
The one change I would make is to not hard-code the year portion but instead use the year specified in the date parameter. This way the method will work in future years. Even better would be to read the peak date ranges from some other data source, so they can be modified without having to recompile the code. But the basic idea I'm suggesting would look like this:
public bool IsInPeakSeason(DateTime date)
{
var startPeak = new DateTime(date.Year, 06, 15);
var endPeak = new DateTime(date.Year, 08, 15);
return date >= startPeak && date < endPeak;
}
as #frontear mentioned, the error is in regards to this line:
DateTime dateCheck >= date1 && dateCheck <date;
You are attempting to use dateCheck without having first assigning a value to it. With the code below, you can omit dateCheck entirely like so, in a single line:
return (date >= new DateTime(2019, 06, 15) && date <= new DateTime(2019, 08, 15));
I just cannot figure this out....Damnit! Please see the calling method in the second code snippet. You'll see a commented out line that reads //_time = time.ToUTCString(); Go to the first code snippet to see the method ToUTCString(). You can see that it takes the datetime, converts it to Universal Time and subtracts the UnixEpoch to get the TotalSeconds. Then it converts that value to Int64() and finally to a string. I tried calling the methos ToLocalString but that's changing the date as well.
The date that I pass in is the date that I want to be converted to Int64 and eventually to a string. The datetime I pass in. Not changed.
I don't want to change the date that is passed in. I always pass in the date starting with 12:00:00AM (or 00:00:00) and that is the time I always want. Both of these methods change the date and or time. The date I pass in is 06/01/2017 12:00:00AM but sometimes it gets changed to 05/31/2017 04:00:00 or it keeps the date but the time is wrong. Dark Sky requires the date to be a value of Convert.ToInt64(milliseconds) and then converted to a string.
Does anybody know how to get the exact date and time that is passed in converted to Int64 using milliseconds?
I have the following Extensions class:
public static class Extensions
{
private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static DateTime ToDateTime(this Int64 _input)
{
return UnixEpoch.AddSeconds(_input);
}
public static string ToLocalString(this DateTime _input)
{
// _input = {6/1/2017 12:00:00 AM} System.DateTime
var milliseconds = _input.ToLocalTime().Subtract(UnixEpoch).TotalSeconds;
return Convert.ToInt64(milliseconds).ToString();
// I want to get the milliseconds for {6/1/2017 12:00:00 AM}
// I don't want the date or time to change
}
public static string ToUTCString(this DateTime _input)
{
// _input = {6/1/2017 12:00:00 AM} System.DateTime
var milliseconds = _input.ToUniversalTime().Subtract(UnixEpoch).TotalSeconds;
return Convert.ToInt64(milliseconds).ToString();
// I want to get the milliseconds for {6/1/2017 12:00:00 AM}
// I don't want the date or time to change
}
}
This is the calling method:
public ForecastIORequest(string apiKey, float latF, float longF, DateTime time, Unit unit, Language? lang = null, Extend[] extend = null, Exclude[] exclude = null)
{
_apiKey = apiKey;
_latitude = latF.ToString(CultureInfo.InvariantCulture);
_longitude = longF.ToString(CultureInfo.InvariantCulture);
//_time = time.ToUTCString();
_time = time.ToLocalString();
//DateTime t = _time.
_unit = Enum.GetName(typeof(Unit), unit);
_extend = (extend != null) ? RequestHelpers.FormatExtendString(extend) : "";
_exclude = (exclude != null) ? RequestHelpers.FormatExcludeString(exclude) : "";
_lang = (lang != null) ? RequestHelpers.FormatLanguageEnum(lang) : Language.en.ToString();
}
There's a fundamental problem with the way you're handling dates here, and if I boil it down to one thing, I think the problem is that ToUniversalTime() doesn't work the way you think it does.
What ToUniversalTime() does is, simply giving the UTC time of a time that's defined in a different time zone. For example, say my local time is UTC-7. So if I define a DateTime object without specifying DateTimeKind and set the value to, say, 2017/6/1 9:00:00, that means, at that time the actual UTC time is 2017/6/1 16:00:00 at that time, and ToUniversalTime() will give you a DateTime object with that value.
Let me change your ToUTCString() method a little bit and show you the problem with it. It's returning a long value instead of string now, and I break down the first line of code into two.
public static long ToUTC(this DateTime _input)
{
var utcTime = _input.ToUniversalTime();
var totalSeconds = utcTime.Subtract(UnixEpoch).TotalSeconds;
return Convert.ToInt64(totalSeconds);
}
And notice that in your Extensions class, the UnixEpoch object's DateTimeKind is set to UTC. I changed the date to 2017/6/1 8:00:00 for the ease of understanding.
private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0, DateTimeKind.Utc);
public static DateTime ToDateTime(this Int64 _input)
{
return UnixEpoch.AddSeconds(_input);
}
Now let's call that method with a DateTime object whose DateTimeKind is set to UTC.
// dateObj will have time 2017/6/1 9:00:00 _in UTC_.
var dateObj = new DateTime(2017, 6, 1, 9, 0, 0, DateTimeKind.Utc);
// This method converts to UTC, but it's already in UTC, so no actual conversion takes place.
// Then subtracts UnixEpoch from it, which is also in UTC.
long dateInLong = dateObj.ToUTC();
// The difference is one hour, so dateInLong will be 3600.
Console.WriteLine(dateInLong);
// This method adds the above difference to UnixEpoch, and displays the time.
Console.WriteLine(dateInLong.ToDateTime());
Now, here, everything is in UTC and you should see output as expected, like below:
3600
6/1/2017 09:00:00
All good so far.
Now change things a bit, and let's set our dateObj to local instead of UTC, as you do in your example.
// Notice that the object is in local time now.
var dateObj = new DateTime(2017, 6, 1, 9, 0, 0);
long dateInLong = dateObj.ToUTC();
Console.WriteLine(dateInLong);
Console.WriteLine(dateInLong.ToDateTime());
Now, the above dateObj will have time 9:00:00, but in my local time. My actual location is UTC-7 so note that this means 9AM local time for me is 4PM UTC. But note that we haven't changed the UnixEpoch object, which is still in UTC and time is set to 8AM UTC in it. And therefore, dateInLong will be 28,800 (8 hours x 60 mins x 60 seconds). So when your ToDateTime() method is called, it adds 28,000 seconds to 8AM UTC time, and returns as a DateTime object, of which time now is 4PM UTC.
28800
6/1/2017 16:00:00
And that's why depending on the time you set your dateObj to, your output changes time as you said.
Solution
You need to decide which time zone to use, and stick to that. One option would be to get rid of all the UTC conversions and have all times set in local time.
public static class Extensions
{
// NOT set to UTC
private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0);
public static DateTime ToDateTime(this Int64 _input)
{
return UnixEpoch.AddSeconds(_input);
}
public static long ToUTC(this DateTime _input)
{
// NOT converted to UTC. So... change variable names accordingly.
var utcTime = _input;
var totalSeconds = utcTime.Subtract(UnixEpoch).TotalSeconds;
return Convert.ToInt64(totalSeconds);
}
}
class Program
{
static void Main(string[] args)
{
// Notice that the object is in local time and NOT UTC.
var dateObj = new DateTime(2017, 6, 1, 9, 0, 0);
long dateInLong = dateObj.ToUTC();
Console.WriteLine(dateInLong);
Console.WriteLine(dateInLong.ToDateTime());
Console.ReadLine();
}
}
The other option, set EVERYTHING to UTC, but then you'll have to make sure that the DateTime object on which you call ToUTC() is defined in UTC and not local.
So:
private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0, DateTimeKind.Utc);
And
var utcTime = _input.ToUniversalTime();
And finally
var dateObj = new DateTime(2017, 6, 1, 9, 0, 0, DateTimeKind.Utc);
BUT...
I see a bigger problem with you code, looking at the second code snippet. In the ForecastIORequest() constructor, you're saving time as a string. And that's not an ideal solution in my opinion. Because as you found the hard way, depending on what time zone the calling object was created, your time difference will be, well, different. And you'd have no way of knowing which.
I'd rather store the DateTime object as it is, and read it and calculate the difference when needed, taking into account time zones.
Hope this helps.
See DateTime.Ticks - there are 10,000 ticks in a millisecond. Simply take DateTime.Ticks / 10000 (ten thousand) and you have your milliseconds.
Here's a simple extension method to get the milliseconds as a long (that's Int64):
public static long ToMilliseconds(this DateTime dateTime)
{
return dateTime.Ticks / 10000;
}
I've created an array of DateTime objects. However when doing so by default the array has the time portion attacthed. I need to this removed to compare to another date which is simply in the "dd/MM/yyyy" format.
Creating the array:
DateTime[] exclusionDates = new DateTime[] { new DateTime(2017, 1, 1) };
I'm trying to compare that with
monthlyCalendar.SelectionEnd.Date == excluHarry[0].Date
How do I remove the time portion to the element of the array?
Thanks.
You are already excluding the time portion when you use the .Date on the DateTime object.
Also, a DateTime object has no format, it only gets a format when you call .ToString() on it, your monthlyCalendar object calls .ToString("dd/MM/yyyy") internally before displaying it to the user, that is the only reason you see it in that form from the user's perspective.
.Date from a DateTime object will get you what you looking for without having to got to string conversion. I have attached example code with two DateTime objects with same date but with different times. The if statement compares only the date portion. Please do accept the answer that helped you the most. Welcome to stack overflow
using System;
namespace DateObject
{
class Program
{
static void Main(string[] args)
{
DateTime[] exDates = new DateTime[] {new DateTime(2017, 1, 1)};
var dt = exDates[0].Date;
//new date with a different time
DateTime t = new DateTime(2017, 1, 1, 5, 30, 23);
//compare the two for date part only --exclude the time in the comparision
if (dt.Equals(t.Date))
{
Console.WriteLine("Dates are the same without comparing the time");
}
}
}
}
There is C code :
time1=((double)dt1-25569.0)*86400.0;
it's convert from TDateTime (VCL) to time_t format in seconds, so finally I need to get time_t format from .NET DateTime
about time_t :
It is almost universally expected to be an integral value representing
the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC. This
is due to historical reasons, since it corresponds to a unix
timestamp, but is widely implemented in C libraries across all
platforms.
So to get seconds in .NET I'm doing this (F#):
let seconds(dt : DateTime) =
(dt.Ticks/10000000L)
or on C# (to use more popular C# tag) :
Int64 seonds(DateTime dt)
{ return (dt.Ticks/ ((Int64)10000000)); }
// hope it works, but please correct if I mistaken
As far as I understand it's time from 12:00:00 Jan 1, 0001 UTC.
So to use time_t format I need to add 1970 years in seconds.
So final function must be (F#):
let seconds(dt : DateTime) =
(dt.Ticks/10000000L) + 31536000*1970
C# :
Int64 seonds(DateTime dt)
{ return (dt.Ticks/ ((Int64)10000000)) + 31536000*1970; }
I really afraid I made mistake here. Please examine this solution ! (check if this is done right)
Thank you
try
(dt - new DateTime (1970, 1, 1)).TotalSeconds
see
http://msdn.microsoft.com/en-us/library/system.timespan.totalseconds.aspx
http://msdn.microsoft.com/en-us/library/xcfzdy4x.aspx
this seems a little tidier? You could make the epoch a static datetime if you will be using it a lot.
DateTime date = DateTime.Now;
DateTime epoch = new DateTime(1970, 1, 1);
TimeSpan span = (date - epoch);
double unixTime = span.TotalSeconds;
I suggest the following code. It seems to better transport the meaning of the code
private static readonly DateTime REFERENCE = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
Int64 seconds(DateTime dt)
{
return (dt - REFERENCE).TotalSeconds;
}
In C#:
Int64 Secs(DateTime dt)
{
var delta = dt - new DateTime(1970, 1, 1);
return Convert.ToInt64(delta.TotalSeconds);
}
After reading #jheriko's comment on the accepted answer I wrote a quick console app to test whether time() from msvcrt.dll produced differing results to calculations using the managed date/time functions, which fortunately they do not, provided UTC is used. Generally speaking, wherever possible, dates and times should be calculated with and stored in UTC as a common base, and then converted back to the relevant timezone for display if necessary.
For reference, and to illustrate different ways of arriving at the number of seconds between 1st Jan 1970 and now, my test code was:
class Program
{
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern int time(int* timer);
static unsafe void Main(string[] args)
{
DateTime now = DateTime.Now;
DateTime utc_now = DateTime.UtcNow;
int time_t_msvcrt = time(null);
int time_t_managed = (int)Math.Floor((now.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds);
int time_t_managed_2 = (int)Math.Floor((utc_now - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds);
Console.WriteLine(time_t_msvcrt == time_t_managed);
Console.WriteLine(time_t_msvcrt == time_t_managed_2);
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime time_t_now = epoch.Add(TimeSpan.FromSeconds(time_t_msvcrt));
long now_secs = now.Ticks / 10000000L;
long utc_now_secs = utc_now.Ticks / 10000000L;
long time_t_now_secs = time_t_now.Ticks / 10000000L;
Console.WriteLine(time_t_now_secs == now_secs);
Console.WriteLine(time_t_now_secs == utc_now_secs);
Console.ReadLine();
}
}
This produces the output
True
True
True
True
as expected.
Would appreciate it if anyone can help me figure out to substract 2 datetime fields to get the days left difference.
This is very easy to do with C#. For comparing DateTimes, we have a class called TimeSpan. The TimeSpan structure, in this case, would be defined as the difference between your two datetimes.
Let's say that your DateTimes are called start and end.
DateTime start = new DateTime(2009, 6, 14);
DateTime end = new DateTime(2009, 12, 14);
We have established our DateTimes to June 14, 2009 and December 14, 2009.
Now, let's find the difference between the two. To do this, we create a TimeSpan:
TimeSpan difference = end - start;
With this TimeSpan object, you can express the difference in times in many different ways. However, you specifically asked for the difference in days, so here's how you can get that:
Console.WriteLine("Difference in days: " + difference.Days);
Thus, the property is called TimeSpan.Days.
Final Code
//establish DateTimes
DateTime start = new DateTime(2009, 6, 14);
DateTime end = new DateTime(2009, 12, 14);
TimeSpan difference = end - start; //create TimeSpan object
Console.WriteLine("Difference in days: " + difference.Days); //Extract days, write to Console.
For more information on using the TimeSpan structure, see this MSDN documentation (especially the C# examples).
Hope I helped!
UPDATE: Some answers have suggested taking doing subtraction in one step, such as with:
int days = (dt2 - dt1).Days;
or
int numDaysDiff = Math.Abs(date2.Subtract(date1).Days);
However, they are the same thing as in my answer, only shortened. This is because the DateTime.Subtract() method and the subtraction operator of DateTimes returns a TimeSpan, from which you can then access the amount of days. I have specifically used the longer approach in my code sample so that you clearly understand what is going on between your DateTime and TimeSpan objects and how it all works. Of course, the other approaches I just mentioned are fine, too.
UPDATE #2:
A very similar question was asked before, and it can be found here. However, the main point of that question was why the code sample (which is essentially equivalent to that of all the answers) sometimes provides an answer which is a day off. I think this is also important to this question.
As the main answer to the other question suggests, you can use this code:
int days = (int)Math.Ceiling(difference.TotalDays);
This code uses Math.Ceiling, which, according to MSDN, is:
Returns the smallest integral value
that is greater than or equal to the
specified double-precision
floating-point number.
How Do You Want to Count the Days?
Thus, we now have an issue with how you want to count the days. Do you want to count part of a day (such as .5 of a day) as:
A full day - this would use Math.Ceiling to round up TimeSpan.TotalDays, so that you're counting started days.
Part of a day - you can just return the TimeSpan.TotalDays (not rounded) as a decimal (in the double datatype)
Nothing - you can ignore that part of a day and just return the TimeSpan.Days.
Here are code samples for the above:
Counting as a full day (using Math.Ceiling() to round up):
//establish DateTimes
DateTime start = new DateTime(2009, 6, 14);
DateTime end = new DateTime(2009, 12, 14);
TimeSpan difference = end - start; //create TimeSpan object
int days = (int)Math.Ceiling(difference.TotalDays); //Extract days, counting parts of a day as a full day (rounding up).
Console.WriteLine("Difference in days: " + days); //Write to Console.
Counting as part of a day (NOT using Math.Ceiling(), instead leaving in decimal form as a part of a day):
//establish DateTimes
DateTime start = new DateTime(2009, 6, 14);
DateTime end = new DateTime(2009, 12, 14);
TimeSpan difference = end - start; //create TimeSpan object
double days = difference.TotalDays; //Extract days, counting parts of a day as a part of a day (leaving in decimal form).
Console.WriteLine("Difference in days: " + days); //Write to Console.
Counting as nothing of a day (rounding down to the number of full days):
//establish DateTimes
DateTime start = new DateTime(2009, 6, 14);
DateTime end = new DateTime(2009, 12, 14);
TimeSpan difference = end - start; //create TimeSpan object
int days = difference.TotalDays; //Extract days, counting parts of a day as nothing (rounding down).
Console.WriteLine("Difference in days: " + days); //Write to Console.
Use
TimeSpan
DateTime departure = new DateTime(2010, 6, 12, 18, 32, 0);
DateTime arrival = new DateTime(2010, 6, 13, 22, 47, 0);
TimeSpan travelTime = arrival - departure;
The easiest way out is, making use of TimeSpan().
This Subtract function will return you the difference between two dates in terms of time span. Now you can fetch fields like days, months etc. To access days you can make use of
Here is the sample code;
VB.Net code;
Dim tsTimeSpan As TimeSpan
Dim ldDate1 as Date
Dim ldDate2 as Date
'Initialize date variables here
tsTimeSpan = ldDate1 .Subtract(ldDate2)
Dim NumberOfDays as integer = tsTimeSpan.days
C#.Net code;
DateTime lDate1;
DateTime lDate2;
TimeSpan tsTimeSpan ;
int NumberOfDays;
//Initialize date variables here
tsTimeSpan = ldDate1 .Subtract(ldDate2);
NumberOfDays = tsTimeSpan.days;
DateTime dt1 = new DateTime(2009,01,01,00,00,00);
DateTime dt2 = new DateTime(2009,12,31,23,59,59);
int days = (dt2 - dt1).Days;
Number of Days Difference
These answers take the number of days as an int from the System.TimeSpan structure that is the result of subtracting two System.DateTime fields...
Quick answer - gets the number of days difference.
int numDaysDiff = date2.Subtract(date1).Days;
Alternate answer - uses Math.Abs to ensure it's not a negative number, just in case the dates might be supplied in either order.
int numDaysDiff = Math.Abs( date2.Subtract(date1).Days );
Some sample data to finish it off using System namespace:
// sample data
DateTime date1 = DateTime.Now;
DateTime date2 = DateTime.Now.AddDays(10);
MSDN References (and more sample code ):
System.TimeSpan structure
System.DateTime structure
System.Math.Abs(..) method
DateTime theDate = DateTime.Today;
int datediff = theDate.Subtract(expiryDate).Negate().Days;
if expiryDate > theDate then you get Negative value: -14
expiryDate is less than theDate then you get positive value: 14
You May obviously want this in a scenario such as
Send a Notification Email 14days before expiry
Send another notification Email 14 days after expiry
You need a difference that could be negative value
You should look at TimeSpan.
To get the exact days ignoring the time section
DateTime d1 = Convert.ToDateTime(DateTime.Now.ToShortDateString());
DateTime d2 = Convert.ToDateTime(DateTime.Now.AddDays(46).ToShortDateString());
var days = Convert.ToInt32(d2.Subtract(d1).TotalDays)