I'm trying to find better way to convert DateTime to unix timestamp in C#
I find out that there is a DateTimeOffset.ToUnixTimeMilliseconds method:
public long ToUnixTimeMilliseconds()
{
return this.UtcDateTime.Ticks / 10000L - 62135596800000L;
}
What this method means? What the constants are used?
UPD:
I guess 10000L is converting from FRAME to Milliseconds. But what about 62135596800000L?
To explain this method:
public long ToUnixTimeMilliseconds()
{
return this.UtcDateTime.Ticks / 10000L - 62135596800000L;
}
DateTime.Ticks units are 100 nanosecond intervals.
Dividing this by 10_000 yields milliseconds, which explains the division by 10000L.
This is because one nanosecond is one billionth of a second, or one millionth of a millisecond.
To convert a nanosecond to a millisecond you would therefore divide by 1_000_000.
However, the ticks are 100 nanosecond units, so instead of dividing by 1_000_000 you would have to divide by 1_000_000/100 = 10_000. That's why you divide the 100 nanosecond units by 10_000 to get milliseconds.
The Unix epoch (which corresponds to a Unix time of zero) is midnight on 1st January 1970.
The DateTime epoch (which corresponds to a DateTime.Ticks value of zero) is 1st January 0001.
The number of milliseconds between 1st January 0001 and 1st January 1970 is 62135596800000. This explains the subtraction of 62135596800000.
And there you have it!
Note: You can compute an approximate value for the number of milliseconds as follows:
Approximate number of days per year = 365.24219
Number of years between 0001 and 1970 = 1969
Thus, total approx milliseconds = 1969 * 365.24219 * 24 * 60 * 60 * 1000
= 62135585750000
The exact figure is much harder to calculate, but it comes out to 62135596800000 as used in the formula above.
In fact, from inspection of the source code we can find the following:
public long ToUnixTimeSeconds() {
// Truncate sub-second precision before offsetting by the Unix Epoch to avoid
// the last digit being off by one for dates that result in negative Unix times.
//
// For example, consider the DateTimeOffset 12/31/1969 12:59:59.001 +0
// ticks = 621355967990010000
// ticksFromEpoch = ticks - UnixEpochTicks = -9990000
// secondsFromEpoch = ticksFromEpoch / TimeSpan.TicksPerSecond = 0
//
// Notice that secondsFromEpoch is rounded *up* by the truncation induced by integer division,
// whereas we actually always want to round *down* when converting to Unix time. This happens
// automatically for positive Unix time values. Now the example becomes:
// seconds = ticks / TimeSpan.TicksPerSecond = 62135596799
// secondsFromEpoch = seconds - UnixEpochSeconds = -1
//
// In other words, we want to consistently round toward the time 1/1/0001 00:00:00,
// rather than toward the Unix Epoch (1/1/1970 00:00:00).
long seconds = UtcDateTime.Ticks / TimeSpan.TicksPerSecond;
return seconds - UnixEpochSeconds;
}
// Number of days in a non-leap year
private const int DaysPerYear = 365;
// Number of days in 4 years
private const int DaysPer4Years = DaysPerYear * 4 + 1; // 1461
// Number of days in 100 years
private const int DaysPer100Years = DaysPer4Years * 25 - 1; // 36524
// Number of days in 400 years
private const int DaysPer400Years = DaysPer100Years * 4 + 1; // 146097
// Number of days from 1/1/0001 to 12/31/1600
private const int DaysTo1601 = DaysPer400Years * 4; // 584388
// Number of days from 1/1/0001 to 12/30/1899
private const int DaysTo1899 = DaysPer400Years * 4 + DaysPer100Years * 3 - 367;
// Number of days from 1/1/0001 to 12/31/1969
internal const int DaysTo1970 = DaysPer400Years * 4 + DaysPer100Years * 3 + DaysPer4Years * 17 + DaysPerYear; // 719,162
Which we can now use to calculate the number of milliseconds to 1970:
719162 (DaysTo1970) * 24 (hours) * 60 (minutes) * 60 (seconds) * 1000 (milliseconds)
= 62135596800000
621355968000000000 is the correct amount of Ticks defined by DateTime
The accepted answer makes it appear like DateTime may produce undefined output different from what you can expect if you actually use it.
new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks
// 621355968000000000
Run it online yourself: https://dotnetfiddle.net/jU0SIp
/// <summary>
/// Convert Ticks to Unix Timestamp
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
public static long ToUnixTimestamp(long time)
{
return (time - 621355968000000000) / TimeSpan.TicksPerMillisecond;
}
You could replace TimeSpan.TicksPerMillisecond with 10000 if you wanted (like your example), It is just a constant for There is 10,000 ticks in a millisecond
Related
I am trying to figure out final price based on wage multiplied by hours.
Here is my code
Why if the hours are 02:30:00 and the wage: $14 is my total 2?
TimeSpan duration = TimeSpan.Parse("02:30:00");
int wage = 14;
var result = (duration.Hours + (duration.Minutes / 60) * wage);
First, the expression is actually evaluated as:
duration.Hours + ((duration.Minutes / 60) * cleaner.Price)
Second, you are doing integer division, so 30/60 will result in 0, leaving you with the value 2 i.e. the Hours part.
To fix the issue, you can do something like the below:
(duration.Hours + ((decimal)duration.Minutes / 60)) * 14;
Alternatively, you can skip this component-wise calculation, and just use the TotalHours property instead:
duration.TotalHours * 14
Hey everyone I want to know that working of get minutes from hours.
I understand this:
test sample 1:-
var result = TimeSpan.FromHours(2.5);
var hours = (int)result.TotalHours;
var minutes = result.Minutes;
output
hours = 2
minutes = 30
it's calculate minute 6*5 = 30
test sample 2:-
var result = TimeSpan.FromHours(2.123);
var hours = (int)result.TotalHours;
var minutes = result.Minutes;
output
hours = 2
minutes = 7
how it calculate minute = 7
please help me
When you're getting TimeSpan from hours with floats, the float part is considered as percentage of minutes in hour. Hour has 60 minutes, so 0.123 from 60 = 7 (12.3%).
you are converting 2.5 and 2.123 to int and int will truncate the rest of the value after the . thats why you get 2
the 30 comes from the 2.5 because 0.5 is half which is 1/2 and 1/2 * 60 = 30
same thing happens with the.123 and the 7 minutes
Internally, TimeSpan holds the duration as a single long, in units of 100 nanoseconds. It calls these ticks.
The implementation defines the following constants:
public const long TicksPerMillisecond = 10000;
private const double MillisecondsPerTick = 1.0 / TicksPerMillisecond;
public const long TicksPerSecond = TicksPerMillisecond * 1000; // 10,000,000
private const double SecondsPerTick = 1.0 / TicksPerSecond; // 0.0001
public const long TicksPerMinute = TicksPerSecond * 60; // 600,000,000
private const double MinutesPerTick = 1.0 / TicksPerMinute; // 1.6666666666667e-9
public const long TicksPerHour = TicksPerMinute * 60; // 36,000,000,000
private const double HoursPerTick = 1.0 / TicksPerHour; // 2.77777777777777778e-11
public const long TicksPerDay = TicksPerHour * 24; // 864,000,000,000
private const double DaysPerTick = 1.0 / TicksPerDay; // 1.1574074074074074074e-12
When you create a TimeSpan from a number of hours, it simply performs something similar to the following calculation (I've simplified this a bit from the actual code by removing the rounding and error checking code):
long _ticks = (long)(hours * TicksPerHour);
When you ask a TimeSpan for TotalMinutes it converts the ticks to minutes as follows:
public double TotalMinutes {
get { return _ticks * MinutesPerTick; }
}
There's nothing at all complicated going on here.
0.1 h -> 6 min
0.2 h -> 12 min
...
0.5 h -> 30 min
...
1.0 h -> 60 min respectively 1h 0 min
See MSDN:
TimeSpan.Minutes Gets the minutes component of the time interval represented by the current TimeSpan structure. Returns
int
and
TimeSpan.TotalMinutes Gets the value of the current TimeSpan structure expressed in whole and fractional minutes. Returns
double
I have a custom solution that checks if a web-site is online, every 1 hour.
The result is something like this: (there is one entry per day)
There are 24 entries in a day (every hour). And every hour has a availability percentage (100%, 95%, 0% ... and so forth).
My questions are:
how can I get up-time and downtime in percentage?
how can I calculate up-time and downtime using these values between 2 dates DateTime and get the result in seconds?
The up-time is easy:
sum of all values divided by 24 (entries) which is 99.67%
Then for downtime, can I just do 100 - 99.67 = 0.33 % ?
I have some issues in getting the up-time/downtime in seconds between 2 dates DateTime
For example: if the range dates are 20.04.2015 - 26.05.2015
I think I should do like this:
For each day calculate the up-time as above (sum of all daily values divided by 24 entries) and assuming the following values:
20.04.2015: 96.67%
21.04.2015: 100.00%
22.04.2015: 92.00%
23.04.2015: 96.67%
24.04.2015: 100.00%
25.04.2015: 100.00%
26.04.2015: 100.00%
Now the sum of the above values divided by the number of days (7 days between 20.04 and 26.04) which makes 97.91 % availability between 20.04 and 26.04.
I assume to get 97.91 % up-time in seconds I should do like this:
CultureInfo provider = CultureInfo.InvariantCulture;
DateTime first = DateTime.ParseExact("20.04.2015", "dd.MM.yyyy", provider);
DateTime last = DateTime.ParseExact("26.04.2015", "dd.MM.yyyy", provider);
TimeSpan time = last - first;
decimal secondsUptime = ((time.Days * 86400)/100) * 97.91m; //97.91 is the uptime calculated above for the time period.
// The problem is how to get this?
decimal secondsDowntime = ?
What I have done so far, is this the correct approach?
How to get the secondsDowntime?
If you already have the Up time percent, All you have to do is very simple math:
decimal PercentDownTime = 100 - PercentUpTime;
decimal SecondsUpTime = (time.Seconds / 100) * PercentUpTime;
decimal SecondsDownTime = (time.Seconds / 100) * PercentDownTime;
Thanks to Robert for reminding us the TotalSeconds property of TimeSpan, but In this case it's ok to use the Seconds property.
Hold up... Ur input numbers are wrong. If u measure once per hour and display the hourly results than how does ur 11:00 have 97%? It should be 100% or 0% its either up or down that hour.... Unless u actually do more calculations in that hour... But even then to get 97 u would have to do at least 100 tests that hour and 3 of them were down.
But if ur numbers are correct the formulas are this...
Uptime % = (sum of the uptime percentages) / (number of measurements) × 100
Uptime % = (sum of uptime) / 24 × 100
Downtime % = 100 - (uptime %)
Seconds of uptime = (number of hours measured or to consider) × 3600 × (uptime %) / 100
Seconds of downtime = (number of hours measure or to consider × 3600) - (seconds of uptime)
Note 3600 is the number of sec in an hour so we multiply the hours by that to get us to the wanted time unit of seconds.
Note Replace uptime % with a number between 0 and 100. Not 0 and 1. If u use 0 to 1 then dont do the last division by 100.
I am dividing two doubles in .NET and using the result object to work out an end date from a start date by calling (dtStart is predefined):
var dValue = 1500.0/8400.0;
var dtEnd = dtStart.AddDays(dValue);
After inspecting dtEnd I found that the result was only accurate to the nearest millisecond. After looking it up I found that .AddMilliseconds etc. all round the number and TimeSpan.FromDays does a similar thing. I was wondering if there was a reason why this rounding was done since it seems like the only way to get the correct value here is to use .AddTicks?
For reference .AddDays calls (where MillisPerDay = 86400000)
public DateTime AddDays(double value)
{
return Add(value, MillisPerDay);
}
which calls
private DateTime Add(double value, int scale)
{
long millis = (long)(value * scale + (value >= 0? 0.5: -0.5));
if (millis <= -MaxMillis || millis >= MaxMillis)
throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_AddValue"));
return AddTicks(millis * TicksPerMillisecond);
}
Edit: After thinking things over, I now realize the first version of my answer was wrong.
Here are the comments in Microsoft's source code:
// Returns the DateTime resulting from adding a fractional number of
// xxxxs to this DateTime. The result is computed by rounding the
// fractional number of xxxxs given by value to the nearest
// millisecond, and adding that interval to this DateTime. The
// value argument is permitted to be negative.
These comments appear on five different AddXxxxs(double value) methods, where Xxxx = Days, Hours, Milliseconds, Minutes and Seconds.
Note that this is only for the methods that accept a floating point value. (And one may question whether or not it is a good idea to involve floating point values in date calculations - but that's a topic for another day.)
Now, as the OP correctly points out, these five methods all call this method:
// Returns the DateTime resulting from adding a fractional number of
// time units to this DateTime.
private DateTime Add(double value, int scale) {
long millis = (long)(value * scale + (value >= 0? 0.5: -0.5));
if (millis <= -MaxMillis || millis >= MaxMillis)
throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_AddValue"));
return AddTicks(millis * TicksPerMillisecond);
}
So what is being done is that the value being added to the DateTime is rounded to the nearest number of millisecond before being added. But not the result - only the value being added (or subtracted).
This is actually documented, for example http://msdn.microsoft.com/en-us/library/system.datetime.adddays%28v=vs.110%29.aspx "The value parameter is rounded to the nearest millisecond."
Why it does this I don't know. Maybe the programmers figured that if you're using floating point values you should be aware that your values are typically not completely accurate. Or maybe they want to simulate to some degree Java-style times, which are based on milliseconds.
I want to know how to calculate different pay rates between certain hours.
For example: If someone works from 9am - 5pm they will recieve 1x rate.
if that same person works from 9am - 7pm they will get 1x rate from 9am-5pm and then 1.5x rate from 5pm - 7pm.
However, I am currently using a DateTime.Now for when they start work and a DateTime.Now when they finish the using a time span to calculate the hours in between.
I haven't tried anything because I dunno how to do it.
Here's a try:
static double Rate = 20.0; // 20$ per hour 9am to 5pm
static double TotalPayment(DateTime startTime, DateTime endTime)
{
if (startTime > endTime)
throw new ArgumentException("start must be before end");
if (startTime.Date != endTime.Date)
throw new NotImplementedException("start and end must be on same day");
double totalHours = (endTime - startTime).TotalHours;
double startOfOrdinaryRate = Math.Max(9.0, startTime.TimeOfDay.TotalHours);
double endOfOrdinaryRate = Math.Min(17.0, endTime.TimeOfDay.TotalHours);
double ordinaryHours;
if (startOfOrdinaryRate > endOfOrdinaryRate)
ordinaryHours = 0.0;
else
ordinaryHours = endOfOrdinaryRate - startOfOrdinaryRate;
return 1.0 * Rate * ordinaryHours
+ 1.5 * Rate * (totalHours - ordinaryHours);
}
Do test if it works.