Getting the system's LocalDateTime in Noda Time - c#

What is the idiomatic way to get the system's time as a LocalDateTime in Noda Time? The most direct method I could think of would be
var dt = DateTime.Now
LocalDateTime systemTime = new LocalDateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute);
but given that Noda Time's entire purpose is to replace DateTime with something that has nicer semantics, I assumed there was a preferred method than to use DateTime in the above manner. The best I could come up with using Noda's facilities is
var zone = NodaTime.TimeZones.BclDateTimeZone.ForSystemDefault();
LocalDateTime systemTime = SystemClock.Instance.Now.InZone(zone).LocalDateTime;
but this seems quite verbose.

Your second example is exactly how you would do this. It is intentionally verbose. See Noda Time's design philosophy.
Think of it in three parts:
Get the current moment in time:
// Instant now = SystemClock.Instance.Now; // NodaTime 1.x
Instant now = SystemClock.Instance.GetCurrentInstant(); // NodaTime 2.x
Get the system's time zone. (This is the preferred syntax)
DateTimeZone tz = DateTimeZoneProviders.Bcl.GetSystemDefault();
Apply the time zone to the instant:
ZonedDateTime zdt = now.InZone(tz);
Your last step of getting a LocalDateTime is trivial, but recognize that when you do it, you are stripping away any time zone information. "Local" in NodaTime does not mean "local to the computer where the code is running". (In other words, it's not like DateTimeKind.Local)
Additional things to think about:
You may prefer to abstract the clock using the IClock interface:
IClock clock = SystemClock.Instance;
// Instant now = clock.Now; // NodaTime 1.x
Instant now = clock.GetCurrentInstant(); // NodaTime 2.x
Then you could pass the clock in as a method parameter, or inject it with your favorite DI/IoC framework. (Autofac, Ninject, StructureMap, whatever...). The advantage is then you could use a NodaTime.Testing.FakeClock during your unit tests. See Unit Testing with Noda Time for more details.
You might also prefer to pass in the DateTimeZone so you can run your code anywhere without being tied to the system time zone. This is important for server applications, but less so for desktop/mobile apps.
If you have other work that's using IANA time zones, or if you're using the .NET Standard build of Noda Time, then change step 2 to use the Tzdb provider:
DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
The TZDB zones are much more accurate than the BCL zones. Noda Time will map your system's Windows (BCL) time zone to an IANA (TZDB) time zone in this initial call.
If you have curiosity into why DateTime.Now is so compact while Noda Time is so verbose, try decompiling DateTime.Now or looking at the MS reference sources. You'll see that it's doing essentially the same steps under the hood.

Related

DateTime, the Epoch and DocumentDb

So I read this very interesting blog on working with datetime in Azure DocumentDb. The problem being that, right now, Azure DocumentDb does not support range search on datetime fields. The reason for that is that DocumentDb is based on json and that has no datetime type, therefore one usually puts it in a string of xml datetime format.
(obviously Mongo does not have that issue, it's bson format adds the datetime type (among others))
Anyway, the article describes storing the datetime in json in an epoch (unix) time, essentially storing the datetime as an amount of seconds since 01-01-1970. One problem of epoch is that it does not take leap seconds into account, but I can live with that for now.
My question is that I would also like to store birth dates in such a format. Now I could just take 01-01-1900 as a start date and store the amount of days since that date in an int. While I am pretty sure this would work well, it feels like epoch is a well established concept, but the one for birthdays feels like I am building my own conventions, which is something I generally like to avoid.
Is there any established standard for standardizing date storage as a number? Which date should be the baseline date?
First of all, an update: DocumentDB now supports range indexes on both strings and numbers. You have to set up the indexes correctly for it to work.
Now, to give you a recommendation. I've been successful storing ISO-8601 timestamps as strings. This is the default format used by the DocumentDB SDK for handling DateTime so it's less work than converting to an integer.
ISO-8601 date/time strings have several properties that match your needs.
The alpha-numeric sort order is chronological so it works perfectly as expected with query clauses using >, <, >=, <=, and BETWEEN assuming you have a range index of appropriate precision (-1 for full precision);
They are human readable so if you are browsing a table, the data makes sense;
This format allows for the specification of lower granularity date/time. For instance, you should say "2015-03" to mean the month of march, or "2015-03-24" to mean March 24, 2015. You can then issue a query with this filter "startedOn >= 2015-03-24 AND startedOn < 2015-03-25" to find everything that started on March 24, 2015. This works even when startedOn is stored as a full ISO-8601 string like "2015-03-24T12:34:56.789Z" due to the nature of string comparison.
I've written about this approach here.
The answer by Teo is correct, except that I suspect in terms of being "well established", the billions of Microsoft Excel, LibreOffice, and Lotus 1-2-3 spreadsheets with their own epoch may far outnumber Unix Time usage. Or the billion of Apple Cocoa devices and computers with their own epoch.
Be aware that a couple dozen different epochs have been used by various computer environments. Unix time is far from being alone or even dominant.
Also be aware that there is no such thing as Unix time exactly. Variations include using whole seconds, milliseconds, microseconds, or nanoseconds.
When possible, use a date-time savvy data type. Be sure to study the doc and experiment to understand clearly it's behavior.
Where not possible to use a data type, fallback to using a string in the various ISO 8601 formats. Some of those standard formats are alphabetically chronological in sorting, especially for date-only values: YYYY-MM-DD.
Leap seconds are ignored in every date-time tracking system I know of. Their purpose is to make our hourly clock jive with calendar, so for business purposes the Leap Second is in a sense meant to be ignored.
Date-time work is surprisingly tricky and slippery business. Search StackOverflow to discover the many issues. Try to avoid rolling your own solutions. For C# in particular, look at the Noda Time library.
In my experience i haven't encountered a more 'established' standard than the UNIX epoch. This being said, some architectural/technological aspects of time storage have been discussed before:
Timestamps and time zone conversions in Java and MySQL
I would ask why risk using your own convention? It's a risk because: what if some time you will want to add hours to your day count, maybe to be able to order people based on when exactly during the day they were born. The question can be extended to: what if at some point you want to measure more generic or more fine-grained moments; you would have to translate your entire feature, possibly throughout many layers of your application, to a more generic mechanism/convention. Another (similar) question would be: will you always measure once-in-a-lifetime events for the people in your database or will they be able to create new, unlimited events? As the number of events increases the risk of collision increases too and a day count would not be as suitable as a timestamp measured in seconds or milliseconds.
UNIX time is basically ubiquitous, you have special methods for getting it in most programming languages. The time-keeping architecture i will always support & implement in my projects is this:
http://www.currentmillis.com/tutorials/system-currentTimeMillis.html
As also stated in my answer to the question linked above, the advantages of storing time as milliseconds since the UNIX epoch are:
architecture clarity: server side works with UTC, client side shows
the time through its local timezone
database simplicity: you store a
number (milliseconds) rather than complex data structures like
DateTimes
programming efficiency: in most programming languages you
have date/time objects capable of taking milliseconds since Epoch
when constructed (which allows for automatic conversion
to client-side timezone)
Because you mentioned C#, DateTime.MinValue comes to mind. This would basically be the year 0 (midnight, 1st of January).
Also, this would be some code which would allow you to get the millis since your chosen reference date (whatever it is) but note that 1900 is still different than .NET's 'epoch' (DateTime.MinValue)
// Unix Epoch
(DateTime.UtcNow - new DateTime (1970, 1, 1)).TotalMilliseconds
// NTP Epoch
(DateTime.UtcNow - new DateTime (1900, 1, 1)).TotalMilliseconds

Does the C# method TimeZoneInfo.ConvertTime handle DST?

I have the following list of time zones that a user can choose from, Mountain Standard Time is in there twice for Arizona. These aren't want they see when they choose. I pulled this list of a website that had all of Microsofts time zones. I guess I'm confused if it had Mountain Standard Time listed for the regular states and AZ.
Hawaiian Standard Time
Alaskan Standard Time
Pacific Standard Time
Mountain Standard Time
Mountain Standard Time
Central Standard Time
Central America Standard Time
Eastern Standard Time
U.S. Eastern Standard Time
My question is I'm guessing these don't account for DST, so I'm assuming I need to add something to my conversion to check and see if they're in DST and adjust it accordingly. Here is how I'm doing the conversion now.
TimeZoneInfo time = TimeZoneInfo.FindSystemTimeZoneById(LocationProvider.GetLocation(LocationID).TimeZone.Name);
return TimeZoneInfo.ConvertTime(DateTime.Now, time);
Yes, TimeZoneInfo accounts for DST, so long as you use it properly (which isn't as easy as it might be, admittedly). It's not really clear why you're trying to do what you're doing though...
I know it's confusing that the ID is actually the standard ID for the time zone, but it's still a full time zone that knows about DST. It doesn't just mean "standard time".
(If you get frustrated with DateTime et al and fancy trying Noda Time for all your date/time needs, I'd be happy to help out :)

How to find Current Time of different culture i.e different timezone in c# asp.net?

Like DateTime.Now gives us current date and time with respect to current system.
How can we find Current Time of different culture i.e different timezone using c# asp.net???
I find SystemTimeToTzSpecificLocalTime Function but how can i used this one???
If you're using .NET 3.5 or later, you can use TimeZoneInfo:
TimeZoneInfo otherZone = ...;
DateTime otherZoneTimeNow = TimeZoneInfo.ConvertTime(DateTime.UtcNow, otherZone);
You need to be somewhat careful using TimeZoneInfo - different DateTime "kinds" do different things - you should read the docs for any call you make carefully. (I recently blogged about the problems with DateTime... TimeZoneInfo basically has to handle the ambiguity.)
You can use a service, like the Yahoo! Web Services API, to pull this information and more. You can get time zone, local time, population, etc. with the Yahoo! Web Services API. The biggest drawback to that approach is the maximum daily hit count.
You can check out this link for more details:
http://developer.yahoo.com/flash/maps/classreference/com/yahoo/maps/webservices/geocoder/GeocoderResult.html

to compare Indian time

I want to find out what will be the time in india when clock tick to 1Am mid night in any other country..
How i will find out that through any means
plz help me to find out this
this is to fire birthbay mails at 1AM midnight of that resp country...
.NET 3.5 added the class TimeZoneInfo which should be able to do want you want. Particularly, the TimeZoneInfo.ConvertTime(DateTime, TimeZoneInfo, TimeZoneInfo) method.
You can also use the TimeZoneInfo.GetSystemTimeZones() method to get the list of time zones that are registered in the system.
You might want to look at the method:
TimeZoneInfo.ConvertTime
SQL SERVER 2008 would have the DATETIMEOFFSET data type (which includes the time zone) plus functions like SWITCHOFFSET to switch from one timezone offset to another.
What version are you on?

Get timezone from DateTime

Does the .Net DateTime contain information about time zone where it was created?
I have a library parsing DateTime from a format that has "+zz" at the end, and while it parses correctly and adjusts a local time, I need to get what the specific time zone was from the DateTime object.
Is this possible at all? All I can see is DateTime.Kind, which specifies if time is local or UTC.
DateTime itself contains no real timezone information. It may know if it's UTC or local, but not what local really means.
DateTimeOffset is somewhat better - that's basically a UTC time and an offset. However, that's still not really enough to determine the timezone, as many different timezones can have the same offset at any one point in time. This sounds like it may be good enough for you though, as all you've got to work with when parsing the date/time is the offset.
The support for time zones as of .NET 3.5 is a lot better than it was, but I'd really like to see a standard "ZonedDateTime" or something like that - a UTC time and an actual time zone. It's easy to build your own, but it would be nice to see it in the standard libraries.
EDIT: Nearly four years later, I'd now suggest using Noda Time which has a rather richer set of date/time types. I'm biased though, as the main author of Noda Time :)
No.
A developer is responsible for keeping track of time-zone information associated with a DateTime value via some external mechanism.
A quote from an excellent article here.
A must read for every .Net developer.
So my advice is to write a little wrapper class that suits your needs.
There is a public domain TimeZone library for .NET. Really useful. It will answer your needs.
Solving the general-case timezone problem is harder than you think.
You could use TimeZoneInfo class
The TimeZone class recognizes local time zone, and can convert times between Coordinated Universal Time (UTC) and local time. A TimeZoneInfo object can represent any time zone, and methods of the TimeZoneInfo class can be used to convert the time in one time zone to the corresponding time in any other time zone. The members of the TimeZoneInfo class support the following operations:
Retrieving a time zone that is already defined by the operating
system.
Enumerating the time zones that are available on a system.
Converting times between different time zones.
Creating a new time zone that is not already defined by the
operating system.
Serializing a time zone for later retrieval.
From the API (http://msdn.microsoft.com/en-us/library/system.datetime_members(VS.71).aspx) it does not seem it can show the name of the time zone used.
DateTime does not know its timezone offset. There is no built-in method to return the offset or the timezone name (e.g. EAT, CEST, EST etc).
Like suggested by others, you can convert your date to UTC:
DateTime localtime = new DateTime.Now;
var utctime = localtime.ToUniversalTime();
and then only calculate the difference:
TimeSpan difference = localtime - utctime;
Also you may convert one time to another by using the DateTimeOffset:
DateTimeOffset targetTime = DateTimeOffset.Now.ToOffset(new TimeSpan(5, 30, 0));
But this is sort of lossy compression - the offset alone cannot tell you which time zone it is as two different countries may be in different time zones and have the same time only for part of the year (eg. South Africa and Europe). Also, be aware that summer daylight saving time may be introduced at different dates (EST vs CET - a 3-week difference).
You can get the name of your local system time zone using TimeZoneInfo class:
TimeZoneInfo localZone = TimeZoneInfo.Local;
localZone.IsDaylightSavingTime(localtime) ? localZone.DaylightName : localZone.StandardName
I agree with Gerrie Schenck, please read the article he suggested.
Generally the practice would be to pass data as a DateTime with a "timezone" of UTC and then pass a TimeZoneInfo object and when you are ready to display the data, you use the TimeZoneInfo object to convert the UTC DateTime.
The other option is to set the DateTime with the current timezone, and then make sure the "timezone" is unknown for the DateTime object, then make sure the DateTime is again passed with a TimeZoneInfo that indicates the TimeZone of the DateTime passed.
As others have indicated here, it would be nice if Microsoft got on top of this and created one nice object to do it all, but for now you have to deal with two objects.

Categories

Resources