First of all, sorry about my ignorance and my awful english skills, i work to improve them.So here goes my question:
I want use DateTime.Ticks (instead Guid.NewGuid) in order to calculate an identifier and a question is being raised to me. In my current culture we have 2 days on the year when we change the official time: in octuber we add an hour and in april we remove it.
how does it affect to the ticks value? how ticks value is calulated? As far as i understand based on https://msdn.microsoft.com/en-us/library/system.datetime.ticks%28v=vs.110%29.aspx it seems it is not able to be a repeat value because based on the text (...)It does not include the number of ticks that are attributable to leap seconds(...) .
there could be repeated ticks?, (maybe other question would be how long a tick lasts, depends on the computer? )
If i'm not wrong it cant be repeated.
Moreover, Maybe there could be a lot of stuff i misunderstand so i'm really sorry again...
Even without DST changes, you can observe DateTime.Now.Ticks returning the same value multiple times, due to the granularity of the system clock.
But with DST changing, if you use DateTime.Now, you will indeed see the same values repeating for one hour per year. The Ticks property is just "the number of ticks since the DateTime epoch, in whatever kind of value is represented". (A DateTime value can be one of three "kinds" - universal, local, or unspecified. It's all a bit of a mess.)
If you use DateTime.UtcNow you shouldn't see that if your system clock only moves forward... but it's entirely possible for system clocks to be changed, either manually or in an automated way, to correct them for drift. Basically, it's not a good source of uniqueness on its own.
(In terms of the length of a tick - the tick in DateTime is always 100ns. That's not true for Stopwatch, where you need to use the Frequency property to find out how long a tick is, or use the Elapsed property to just find the elapsed time as a TimeSpan.)
Related
I've read a few posts about similar subjects but nothing seems to answer this question. My database has the following information about a time
Day of the week (a number between 0-6)
Time (a number of milliseconds since midnight in the users local time)
UTC offset ( number of hours different to UTC )
DST Observed (boolean stating if DST is observed in that time zone)
This data represents opening hours. So there is a time for each day. I want to display that time in the users local time making the assumption that each day is in the future
int dayOffset = availability.Day - (int)now.DayOfWeek
if (dayOffset < 0)
dayOffset += 7;
I'm really struggling to get my head around time zones and handling when one time zone might be observing DST while another maybe DOES observe DST but hasn't yet.
My main issue at the moment is I think I need to create a DateTimeOffset object for the non-local time but I'm not sure how to do that as I don't know if DST is in effect or not.
I hope I'm making myself clear. It really is a mind-bending experience working with dates and time!
As indicated by other answers, the usual solution to handling DateTime across time zones would be to store UTC times.
However, considering that you are not referencing an absolute time at a specific date, but instead are referring to a time at an infinite number of days in a specific time zone; storing the time as an UTC time doesn't make sense anymore, since the UTC time (even if we discard the date) would be different depending on the date, due to DST.
The best way to store the time is fairly close to what you have done already.
Your problem is that the time zone information you are storing at the moment is ambiguous, as it does not refer to a specific time zone, but instead refers to properties of the time zone.
To solve this problem, simply store the time zone identifier instead of the UTC offset and DST boolean.
It is now possible for us to construct the DateTime object and convert it to any time zone by using the TimeZoneInfo class:
int dayOffset = availability.Day - (int)DateTime.Today.DayOfWeek;
if (dayOffset < 0)
{
dayOffset += 7;
}
var openingHourStart = DateTime
.SpecifyKind(DateTime.Today, DateTimeKind.Unspecified)
.AddDays(dayOffset)
.AddMilliseconds(availability.Time);
var sourceTimeZone = TimeZoneInfo.FindSystemTimeZoneById(availability.TimeZoneId);
var userTimeZone = TimeZoneInfo.Local;
var convertedOpeningHourStart = TimeZoneInfo.ConvertTime(openingHourStart,
sourceTimeZone,
userTimeZone);
Give a try to Quartz.NET.
It implements evaluation of CronExpressions, and even triggers to fire events at the given time. It can evaluate the next time an event will occur. This may help you out calculating the opening times.
Also, take a look at the cronmaker website: there you can understand the full potential of CronExpressions.
The CronExpressionDescriptor is a DotNET library for transforming CronExpressions into human readable strings.
Another library which I haven't tried yet is [HangFire].(https://www.hangfire.io/)
In this forum post you can find some discussion on how HangFire implements evaluation of RecurringJobs in local timezone with DST, which I believe is a solution for what you are looking for.
A comment to another answer made the problem a little bit more clear.
So, first and foremost, do store only UTC in your database. Really.
Now, since you are not interested in the actual dates, since you are storing working schedules that repeat weekly, the date only becomes relevant once you want to present your times - and when you put them in your database.
So let's first see how you get your times into your database correctly. I'm assuming a user will enter times in their own locale.
Make sure you first create a (localised) DateTime consisting of the current date and the given time (from the user), and transform that to a UTC DateTime (you can keep the current date, it doesn't matter):
var utcDateTime = DateTime.Now.Date
.AddHours(userHours)
.AddMinutes(userMinutes)
.ToUniversalTime();
Now when you are presenting these times to the user, simply go the other way:
var userDateTime = DateTime.Now.Date
.AddHours(utcDateTime.Hour)
.AddMinutes(utcDateTime.Minute)
.ToLocalTime();
And then you can use the userDateTime.Hour and .Minute for display purposes.
You should be leveraging DateTime.ToLocalTime() and TimeZoneInfo.ConvertTimeToUtc() in C# - see https://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime(v=vs.110).aspx.
If you want to store only times that you're open from Monday to Sunday, fine. Have a simple data table to describe only the time for each day (0 = Sunday through 7 = Saturday -- this is .Net's DayOfWeek enumeration). Your lookup table might look like:
0 null
1 08:00:00
2 08:00:00
3 08:00:00
4 08:30:00
5 08:30:00
6 10:30:00
(Use whatever data type works for you--SQL Server 2008+ has a TIME data type, for example. Null can be used for Closed on that day--i.e., no open time.)
When it comes time to display YOUR time to any other user, use must create your UTC time on-the-fly at the moment you are displaying information to the local user.
Conyc provided one approach. My approach uses simple date/time strings. To use my approach, just store time values per day in your database. Then you can look up the open time for any given day. To express that time for another user in any locale, use this code to convert your time to UTC (you can substitute the "08:00:00 AM" string value with a string variable that you populated after looking up the open time in your database):
var StoreOpenTimeInUtc = TimeZoneInfo.ConvertTimeToUtc(Convert.ToDateTime("08:00:00 AM"));
To look up the open time in your database for a particular day in the future, you will need to concatenate the date to your time value, like this:
var StoreOpenTimeInUtc = TimeZoneInfo.ConvertTimeToUtc(Convert.ToDateTime("04/28/2018 08:00:00 AM"));
Once you have an accurate StoreOpenTimeInUtc variable, you can use that as the UTC value on someone else's machine who is anywhere else on planet earth. To convert that UTC value to their local time, use the .NET ToLocalTime() method:
var OpenTimeForLocalUser = StoreOpenTimeInUtc.ToLocalTime();
Note that this approach requires you to store only the open times as shown above. You don't have to worry about dates, local offsets from UTC, or anything else. Just leverage ConvertTimeToUtc() and ToLocalTime() as shown.
I currently use a solution for getting a higher resolution timestamp in C# by taking a start time using DateTime.UtcNow and then using a Stopwatch to add ticks to it as time goes by. I came across Stopwatch.GetTimestamp() as a potential alternative or even better solution, but I cannot find reliable information on exactly what this function returns.
Best source of info seems to be this.
GetTimestamp() returns machine-dependent ticks which can be converted into seconds by dividing by the stopwatch frequency. If I do this, I get a value that appears to be a UTC UNIX timestamp which is exactly what I'm after - but I haven't seen anything that states that this is what I should expect from it.
One clue from MSDN states that:
If the Stopwatch class uses a high-resolution performance counter,
GetTimestamp returns the current value of that counter. If the
Stopwatch class uses the system timer, GetTimestamp returns the
current DateTime.Ticks property of the DateTime.Now instance.
Looking then at DateTime.Ticks, we then see:
The value of this property represents the number of 100-nanosecond
intervals that have elapsed since 12:00:00 midnight, January 1, 0001
(0:00:00 UTC on January 1, 0001, in the Gregorian calendar), which
represents DateTime.MinValue.
I'm therefore not clear how simply dividing some machine-dependent tick-count by the frequency can get me a UNIX 1970+ timestamp? Is it possible that if a high performance timer is not available on the target platform that I might get year 0001-based timestamp instead? Or maybe something else entirely, again depending on the available hi-res timer?
Can you describe your use case? If you're interested in extra precision, I don't see how you could possibly get it by starting out with DateTime.UtcNow, and then, separately, calling Stopwatch.Start() -- if you add Stopwatch.Elapsed to DateTime.UtcNow, the value is going to be inaccurate, because you have no way of knowing how long after the DateTime.UtcNow call that the stopwatch actually started. If you start the stopwatch first, you have the same problem in reverse.
Generally speaking, in .NET 4.6, there is a ToUnixTimeMilliseconds call on DateTimeOffset that may be helpful (e.g. DateTimeOffset.UtcNow.ToUnixTimeMilliseconds())
I am working on an application that needs to set rules for periods of time. The company has different branches, each branch can set its own rules (i.e a branch starts work at 8.30 am, ends work at 17.30 pm, with 30 minutes pause for lunch; another branch start at 9.00, ends at 19.00 with 1 hour pause...)
So I need to define a class (let's call it WorkingDayDefinition for the moment) where start and end are not actually a DateTime, because they are not referred to any specific day in particular.
At the moment the only option I see in C# is using Timespan for setting a duration from the beginning of the day, so that 8.30 pm would be TimeSpan(8,30,0) to be added to the Day part of whichever day.
Is this a best practice in C#?
I searched for third parties libraries that could help me, but so far my best bet is this one:
http://www.codeproject.com/Articles/168662/Time-Period-Library-for-NET
that is not strictly what I need
You could use Noda Time. It provides a LocalTime (see here):
LocalTime is an immutable struct representing a time of day, with no reference to a particular calendar, time zone or date.
For 8.30 you would do something like:
LocalTime openingAt = new LocalTime(8, 30);
To me TimeSpam seems very suitable for what you want. It holds an interval of time, sometimes between two events, but in your case between the start of the day and the time you start/finish work. There is no reason I can think of not to use it just because the name might suggest this wasn't the original intention of the class. Plus it already integrates well with DateTimes for any time calculations you need to do later on down the road.
We are currently rewritting the core of our services, basically we have scheduled tasks that can run on intervals, dates, specific times etc etc etc.
Currently we're wondering if daylightsaving might cause trouble for us, basically we calculate the next possible runtime, based on what days the task should execute and between what times, and what interval. We do this by taking the current time, and adding days/minutes/hours to this DateTime.
We then take this new run time and subtract DateTime.Now from this DateTime, leaving us with the timespan untill the next run.
How ever, what if the current time is 01:50 on a daylightsavings day, we add 20 minutes, which is our set interval, and end up with a time of 02:10, how ever since this is daylightsavinds, it's actually 01:10.
When i subtract the current time (01:50) from the 01:10 (which is actually 02:10) does this return a negative value which i need to work around or does this never ever return a negative value because DateTime is just a long underneath holding the proper information?
Basically, the following code, is the check needed or not?
//Get interval between nextrun and right now!
double interval = (NextRun - DateTime.Now).TotalMilliseconds;
//Check if interval is ever less or equal to 0, should never happen but maybe with daylight saving time?
if(interval <= 0)
{
//Set default value
interval = IntervalInMilliseconds;
}
We believe that this check isn't needed but our googling so far hasn't given us a definative answer.
Use DateTime.UtcNow instead of DateTime.Now EVERYWHERE
First of all, you can try it yourself as it will help you understand how it works.
Essentially, using your example above, if you have 20 minutes to a local time, it would be 2:10 and not 1:10 as the computation is done in local time. If you want to get 1:10, you need to convert local time to universal time, add 20 minutes and then convert back to local time.
If you want real elapsed time, then you have to convert time to universal time before computing time difference. Also, if you work in local time, you won't be able to differentiate ambiguous time when the clock goes back.
I'm having problems deciding on what is the best way is to handle and store time measurements.
I have an app that has a textbox that allows the users to input time in either hh:mm:ss or mm:ss format.
So I was planning on parsing this string, tokenizing it on the colons and creating TimeSpan (or using TimeSpan.Parse() and just adding a "00:" to the mm:ss case) for my business logic. Ok?
How do I store this as in a database though? What would the field type be? DateTime seems wrong. I don't want a time of 00:54:12 to be stored as 1901-01-01 00:54:12 that seems a bit poor?
TimeSpan has an Int64 Ticks property that you can store instead, and a constructor that takes a Ticks value.
I think the simplest is to just convert user input into a integer number of seconds. So 54:12 == 3252 seconds, so store the 3252 in your database or wherever. Then when you need to display it to the user, you can convert it back again.
For periods less than a day, just use seconds as other have said.
For longer periods, it depends on your db engine. If SQL Server, prior to version 2008 you want a datetime. It's okay- you can just ignore the default 1/1/1900 date they'll all have. If you are fortunate enough to have sql server 2008, then there are separate Date and Time datatypes you can use. The advantage with using a real datetime/time type is the use of the DateDiff function for comparing durations.
Most databases have some sort of time interval type. The answer depends on which database you're talking about. For Oracle, it's just a floating point NUMBER that represents the number of days (including fractional days). You can add/subtract that to/from any DATE type and you get the right answer.
As an integer count of seconds (or Milliseconds as appropriate)
Are you collecting both the start time and stop time? If so, you could use the "timestamp" data type, if your DBMS supports that. If not, just as a date/time type. Now, you've said you don't want the date part to be stored - but consider the case where the time period spans midnight - you start at 23:55:01 and end at 00:05:14, for example - unless you also have the date in there. There are standard build in functions to return the elapsed time (in seconds) between two date-time values.
Go with integers for seconds or minutes. Seconds is probably better. you'll never kick yourself for choosing something with too much precision. Also, for your UI, consider using multiple text inputs you don't have to worry about the user actually typing in the ":" properly. It's also much easier to add other constraints such as the minute and second values conting containing 0-59.
and int type should do it, storing it as seconds and parsing it back and forth
http://msdn.microsoft.com/en-us/library/ms187745.aspx