Skip to content

Javascript Send Schedule Date From Local Timezone to Server Time

I am in Hawaii. From Angular, I want to send Pacific Standard Time (PST) to C# Net Core API. It will save it in database and save in Pacific Standard Time. (I didn’t create the architecture, just noting).

The whole Angular Application date/times are written in reference of PST.

Example goal is to Schedule Date at 4:30PM PST

We learned a bug today, if we send a date "2021-03-17T16:30:00" , our application creates new Date("2021-03-17T16:30:00") in Hawaii Timezone misinterprets. Then C# probably does the right thing, and converts any time to Pacific Local time (TimeZoneInfo.ConvertTime(dateTime, TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles")). Thus we incorrectly convert to 7:30PM.

Our API Request Data type is in Date. Would this solution work? however, I feel last 4th line will not account for Daylight savings, or can create issue.

const inputDate = "2021-03-17T16:30:00";
const pstMoment = moment.tz(inputDate, 'America/Los_Angeles');
const clientTimeZoneName = Intl.DateTimeFormat().resolvedOptions().timeZone;
const clientMoment = pstMoment.clone().tz(clientTimeZoneName);
console.log(new Date(clientMoment.format())); // this will send to API
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.33/moment-timezone-with-data-10-year-range.js"></script>

Note: Code resolution should not only work in Hawaii, but other global countries which may Not have Daylight Savings Time. Our schedule datepicker utilizes a string storage type (inputDate).

Typescript class

export interface ScheduleDto { 
   scheduleDate?: Date;

scheduleDate: "2021-03-18T02:30:00.000Z"

C# class

public class ScheduleDto   
{
   public DateTime? ScheduleDate { get; set; }

....

return TimeZoneInfo.ConvertTime(ScheduleDate , TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles"));

Answer

If I understand correctly, the problem is that your current approach on the client-side is just creating a Date object like new Date("2021-03-17T16:30:00"), which is going to use the local time zone to determine the point-in time you’re talking about. You want it to always be interpreted as Pacific time, but you don’t know which offset to use because of DST.

So then, the ultimate answer to your question is – YES, the code you wrote using Moment-timezone, would indeed apply the correct offset. However, it’s a bit verbose. You don’t actually need to do anything with regard to detecting the current local time zone. You can instead just build the Date object with:

moment.tz('2021-03-17T16:30:00', 'America/Los_Angeles').toDate()

Given Moment’s project status, it would be preferred to use Luxon instead (unless you have already extensively used Moment in your project). In Luxon, that would be:

luxon.DateTime.fromISO('2021-03-17T16:30:00', {zone: 'America/Los_Angeles'}).toJSDate()

Or you could use the zonedTimeToUtc function from date-fns-tz.

The point is, since you’re constructing a Date object, you’re always sending some string representation of it over the wire. You appear to be serializing those Date objects with .toISOString(), which will send the UTC equivalent "2021-03-18T02:30:00.000Z". Getting that UTC point in time correct is what matters most.

In your .NET code, if you are receiving that value into a DateTime object, then its Kind property will be set to Utc because of the Z at the end of the string. TimeZoneInfo.ConvertTime will use the Kind property to determine the source time zone for the conversion, and you’ve supplied the destination time zone as Pacific time.

A much simpler approach would be to not use a Date object in your client-side code, but rather you would send the intended date and time over the wire instead, without the offset "2021-03-17T16:30:00". In your .NET code, the DateTime.Kind would be Unspecified. Then you wouldn’t call TimeZoneInfo.ConvertTime at all, because you already have the value in the desired time zone.

Alternatives:

For the TypeScript data type, You could use a string.

In the future, when Temporal is finished and fully integrated into ECMAScript, you could use a PlainDateTime.