6

Ok, So I have a web server that is hosted in the Central Standard Time Zone. The IIS server is configured with that as the Time Zone, so whenever use DateTime.Now on the server or create a new DateTime where the kind is Local, it is in Central time.

The issue is that the site is a (inter)national application and I could have clients anywhere within the US or Canada. One of the things the site has is a "Scheduler" of sorts for scheduling appointments. We decided for ease of development to store all DateTime values on the database in UTC format and that all traffic in and out of the API is in UTC as well. The problem is that I am frequently running into problems when I am creating date/time values on the server side.

Say for example I need to programmatically create an appointment for a client in the Pacific Standard Time zone on the server for 8 am. In the past, I have done things like this:

var appointment = new new DateTime(2015, 04, 17, 08, 00, 00, DateTimeKind.Unspecified)
var utcAppointment = TimeZoneInfo.ConvertTimeToUtc(appointment,
                        TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"))

I do lots of other date/time manipulations as well within my program and am thinking of just going to Nodatime instead. I know I can get the UTC DateTime out of a Nodatime variable fairly easily. What I am confused about is how to create a Nodatime variable for a specific time zone at a specific date/time? All the examples I see have to do with Patterns and reading strings or creating an Instant which is essentially "Now". I want to do something like take an existing BCL DateTime object, regardless of the "Kind", and convert it to a Nodatime object with the specific time zone I set.

I think Nodatime is a great library, but reading the userguide just left me scratching my head about converting in and out of BCL.

SpaceCowboy74
  • 1,367
  • 1
  • 23
  • 46
  • I asked something similar [here](http://stackoverflow.com/q/7553997/397817) but it wasn't originally a NodaTime question. The discussion there might be helpful to future readers of this question. Also I can second Jon Skeet's suggestion of using NodaTime types in Web API where appropriate, e.g. a LocalTime for the time part of your schedule - there is even a helper library for serialisation, NodaTime.Serialization.JsonNet. – Stephen Kennedy Sep 11 '16 at 11:26

1 Answers1

11

What I am confused about is how to create a Nodatime variable for a specific time zone at a specific date/time?

That's relatively easy:

LocalDateTime local = new LocalDateTime(2015, 4, 17, 8, 0, 0);
DateTimeZone zone = DateTimeZoneProviders.Tzdb["America/Los_Angeles"];
ZonedDateTime zonedTime = local.InZoneLeniently(zone);

The "leniently" part really depends on what you want to happen if 8am turns out to be skipped or ambiguous - that won't happen in this case, but it's something to bear in mind. Noda Time lets you deal with this in various ways - the user guide goes into more detail.

Note that if you'd prefer to think in terms of the zone doing the conversion, you can use zone.AtLeniently(local) instead - they're absolutely equivalent.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • If I were to have an existing BCL DateTime object, I take it I could use LocalDateTime.FromDateTime(objectName) as well? – SpaceCowboy74 Apr 17 '15 at 20:05
  • @SpaceCowboy74: Yup, although I'd recommend using Noda Time types as widely as possible. – Jon Skeet Apr 17 '15 at 20:07
  • Understood. Problem is that outside forces and the WebApi itself pass in DateTime objects to me on occasion. I need to consume those to convert to UTC. I sandboxed some and was able to do it with your code above and then passing the zonedTime to EntityFramwork with a ToDateTimeUtc call. – SpaceCowboy74 Apr 17 '15 at 20:10
  • @SpaceCowboy74: Right - you *should* be able to configure a Web API to provide Noda Time values instead of using `DateTime`, but if you want to convert instead, that's fine. – Jon Skeet Apr 17 '15 at 21:22