Why my random DateTime generator make dates outside of range? - c#

I have a function to generate random DateTime in range between two dates... and somehow it makes random dates that comes before minimal date. What's wrong with my code?
public void TestFunct()
{
GenerateRandomTimeBetweenDates(new Random(), DateTime.ParseExact("01.01.2017 00:00:00", "dd.MM.yyyy HH:mm:ss", CultureInfo.InvariantCulture), DateTime.ParseExact("01.02.2017 00:00:00", "dd.MM.yyyy HH:mm:ss", CultureInfo.InvariantCulture));
}
public DateTime GenerateRandomTimeBetweenDates(Random RNG, DateTime dt1, DateTime dt2)
{
int dt1_sec = (int)dt1.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; //calc seconds since Unix epoch
int dt2_sec = (int)dt2.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
int random_sec = RNG.Next(Math.Min(dt1_sec, dt2_sec), Math.Max(dt1_sec, dt2_sec)); //RNG is Random instance. Here I generate seconds amount between two amounts - minimal and maximal.
DateTime random_dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(random_sec); //I try to recreate date by adding generated seconds amount to Unix epoch.
if (random_dt.Year == 2016)
random_dt = random_dt; //this I use to trigger breakpoint
return random_dt;
}

The problem here is ToUniversalTime(). If your dates have kind of Local or Unspecified - ToUniversalTime will convert them to UTC assuming (in case of Unspecified) that they are local. By doing that, your dt1, which is January 1, 2017 will be represented in UTC as a date in 2016 year. When random value is close to minimal value - result will also be in 2016 year. To fix - just remove call to ToUniversalTime(). You can just remove it, because, by documentation of Substract method:
The System.DateTime.Subtract(System.DateTime) method does not
consider the value of the System.DateTime.Kind property of the two
System.DateTime values when performing the subtraction
Note however that it's better to return result with the same kind as inputs, so:
DateTime random_dt = new DateTime(1970, 1, 1, 0, 0, 0, dt1.Kind).AddSeconds(random_sec);
Because otherwise if your input represents local time and result is in UTC - doesn't make much sense.

Related

Unix Timestamp has a UTC difference

I need to convert a Date and Time string to epoch timestamp. I am getting a time difference of 11 hours, (I reckon it is the UTC to local time difference).
using System;
public class Program
{
public static void Main()
{
var output = StringDateToUnixString("08-02-2021 23:59:59", "dd-MM-yyyy HH:mm:ss");
Console.WriteLine($"Result : {output}");
Console.WriteLine("Expected: 1612789199000");
if(output == 1612789199000)
{
Console.WriteLine("Match");
}
else
{
Console.WriteLine("Not a match");
}
}
public static double StringDateToUnixString(string dateString, string currentFormat)
{
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime date = DateTime.ParseExact(dateString, currentFormat, System.Globalization.CultureInfo.InvariantCulture);
return Convert.ToInt64((date - epoch).TotalMilliseconds);
}
}
When I check, epoch and local are in UTC, however (UTC-UTC).TotalMilliseconds, when converted back is local time.
I really appreciate I can update the StringDateToUnixString function so that the Main can work as expected.
Have you tried this. for get unix timestamp:
DateTimeOffset.Now.ToUnixTimeMilliseconds();
and for convert timestamp to date time:
return new DateTimeOffset(1970, 1, 1, 0, 0, 0, 0, TimeSpan.Zero).AddMilliseconds(1612789199000).UtcDateTime;
The problem is caused because you are subtracting two DateTime values that have different meanings. Your epoch variable is UTC based and has its Kind property set to DateTimeKind.Utc, while your date variable is local-time based and has its Kind property set to DateTimeKind.Unspecified.
However, when subtracting or comparing DateTime values - the Kind property is not considered. The operation is based solely on the Ticks property.
Contrast this with DateTimeOffset values, where the offset is taken into account for such operations.
There are a few different ways you could resolve this in your code, and still adjust from a local-time based date/time string to a Unix Timestamp (which is inherently UTC based):
You could convert the date value to UTC after parsing it, before subtracting:
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime dateTime = DateTime.ParseExact(dateString, currentFormat, CultureInfo.InvariantCulture);
return (dateTime.ToUniversalTime() - epoch).TotalMilliseconds;
You could tell DateTime.ParseExact that you'd like a behavior where the input string is assumed to be local time and the output value should be adjusted to UTC. This is done by combining the AssumeLocal and AdjustToUniversal DateTimeStyles flags as follows:
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime dateTime = DateTime.ParseExact(dateString, currentFormat, CultureInfo.InvariantCulture,
DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal);
return (dateTime - epoch).TotalMilliseconds;
You could parse the value as a DateTimeOffset instead of a DateTime. When doing so, if no offset is in the input string, the local time zone is used. This approach also has the advantage of being able to use the built-in ToUnixTimeMilliseconds method:
DateTimeOffset dateTimeOffset = DateTimeOffset.ParseExact(dateString, currentFormat, CultureInfo.InvariantCulture);
return dateTimeOffset.ToUnixTimeMilliseconds();
Note in all three cases, I assumed using System.Globalization; was included at the top of your program, and that I removed Convert.ToInt64 from the result because it is extraneous.

long value to date c#

My server is sending me the following value 13928550480000 which I know represents the date 02/19/2014. But I am not able to figure out how to get to the date from the long value.
I tried various ways of converting long to date using c# date time class but not able to get to the correct date i.e. 02/19/2014
long dateL = 13928550480000;
DateTime dt = new DateTime(dateL);
var dtstr = dt.ToString("MM/dd/yyyy");
var onlyDate = dt.Date;
DateTime start = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime date = start.AddMilliseconds(dateL).ToLocalTime();
var dtstr1 = date.ToString("MM/dd/yyyy");
It looks like your source number represents number of 0.10 ms increments since 1-1-1970 (either that or a typo):
long dateL = 13928550480000;
DateTime start = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime date = start.AddMilliseconds(dateL/10).ToLocalTime();
// ***
// ^------
var dtstr1 = date.ToString("MM/dd/yyyy"); // 02/19/2014
I suspect the time zone difference is irrelevant to your problem.
Did you write too many zeros at the end of your big number? That is, does it really end in 0000 and not just 000?
If it really is 0000, then it appears to be measuring time in 100-microsecond increments (10,000 time increments per second). But it is probably also giving you time in GMT and you are expecting to derive local time from it. The time 1392855048 seconds from Jan. 1, 1970 would be 10 minutes 48 seconds past midnight on Feb. 20, 2014. Depending on your time zone, that could be sometime on Feb. 19 local time.

c# convert UTC to EDT

I know there are a lot of questions on this, BUT I am still confused!
How do I convert from UTC to EDT. i.e. To EST (New York in particular) but with Daylight savings?
I am trying this:
TimeZoneInfo edtZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime utcDT = UnixTimeStampToDateTime(double.Parse(fields[0]));
utcDT.Kind = DateTimeKind.Utc; //THIS LINE IS WRONG
DateTime edtDT = TimeZoneInfo.ConvertTimeFromUtc(utcDT, edtZone);
//Put in for as requested
public static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
{
// Unix timestamp is seconds past epoch
System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
return dtDateTime;
}
Thanks
I suspect your UnixTimeStampToDateTime method is incorrect. Assuming it's taking the number of seconds since the Unix epoch, it should return a DateTime with a Kind of Utc already, e.g.
private static readonly DateTime UnixEpoch =
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static DateTime UnixTimeStampToDateTime(double secondsSinceUnixEpoch)
{
return UnixEpoch.AddSeconds(secondsSinceUnixEpoch);
}
EDIT: Now that we can see the existing implementation - yes, it's inappropriate. There's no reason why you should want to create an Unspecified value and then convert it to a Local one. Using the above should be fine, and more useful in general. Any existing calls which need a system local value should call ToLocalTime on the result of UnixTimeStampToDateTime.
(Alternatively, use my Noda Time project, where you can use Instant.FromSecondsSinceUnixEpoch to get an Instant, and then do whatever you want...)

How to revert engineer number to datetime?

I knew this number 1317820569 is mean 9:16PM Oct 5, 2011.
I don't know where or how the date being converted to the number, but I do know it can be reconstruct back to the date that match with it.
Now, can some master here help me out to enlighten me how can it be done in C# ?
Thanks!
It looks like a UNIX epoch, which is the number of seconds since 1st Jan 1970.
Here's how to do it:
DateTime date = new System.DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(epoch);
You can do the reverse like this:
double epoch = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
Looks like it is the seconds since 1/1/ 1970
DateTime dt = DateTime.Parse("1970/1/1");
dt = dt.AddSeconds(1317820569); //result: 10/5/2011 1:16:09 PM
This looks like a Unix timestamp.
static DateTime ConvertFromUnixTimestamp(double timestamp)
{
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
return origin.AddSeconds(timestamp);
}

ASP.net c# Parse int as datetime

Given a time:
1286294501433
Which represents milliseconds passed since 1970, how do we convert this to a DateTime data type? EG:
transactionTime = "1286294501433";
UInt64 intTransTime = UInt64.Parse(transactionTime);
DateTime transactionActualDate = DateTime.Parse(intTransTime.ToString());
Throws:
String was not recognized as a valid
DateTime.
Please note all times passed into this function are guaranteed to be after 1970.
var dt = new DateTime(1970, 1, 1).AddMilliseconds(1286294501433);
You might also need to specify the DateTimeKind explicitly, depending on your exact requirements:
var dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
.AddMilliseconds(1286294501433);
And to simplify it even further and also take your local timezone into account:
Just create this integer number extension -
public static class currency_helpers {
public static DateTime UNIXTimeToDateTime(this int unix_time) {
return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(unix_time).ToLocalTime();
}
}
And then call it wherever like this:
var unix_time = 1336489253;
var date_time = unix_time.UNIXTimeToDateTime();
The value of date_time is:
5/8/2012 10:00:53 AM
(via: http://www.codeproject.com/Articles/10081/UNIX-timestamp-to-System-DateTime?msg=2494329#xx2494329xx)
Assuming this is unix time its the number of seconds, so
int unixtimestamp=int.Parse(str);
new DateTime(1970,1,1,0,0,0).AddSeconds(unixtimestamp);
like this fetcher guy said.
wiki says
Unix time, or POSIX time, is a system
for describing points in time, defined
as the number of seconds elapsed since
midnight proleptic Coordinated
Universal Time (UTC) of January 1,
1970, not counting leap seconds. I

Categories