I’m trying to work with date-fns-tz in my react-based webpage and couldn’t make the following use-case to work.
I have a date input in a form that should be submitted to the backend that stores the data in local timezone.
A user in GMT+2 timezone selects 14:00 on 1/Feb/2021 in the UI, which correlates to 1612180800 timestamp (as the UI was opened in GMT+2), but it should eventually get sent to the backend as 14:00 in GMT-8, which is actually 1612216800 timestamp.
What’s the right way to get this conversion (from 1612180800 --> 1612216800 ) to work?
I tried to work with various date-fns functions, but hadn’t found the right one.
You'll need two things to make this work correctly:
An IANA time zone identifier for the intended target time zone, such as 'America/Los_Angeles', rather than just an offset from UTC.
See "Time Zone != Offset" in the timezone tag wiki.
A library that supports providing input in a specific time zone.
Since you asked about date-fns, you should consider using the date-fns-tz add-on library.
Alternatively you could use Luxon for this.
In the past I might have recommended Moment with Moment-TimeZone, but you should review Moment's project status page before choosing this option.
Sticking with date-fns and date-fns-tz, the use case you gave is the very one described in the docs for the zonedTimeToUtc function, which I'll copy here:
Say a user is asked to input the date/time and time zone of an event. A date/time picker will typically return a Date instance with the chosen date, in the user's local time zone, and a select input might provide the actual IANA time zone name.
In order to work with this info effectively it is necessary to find the equivalent UTC time:
import { zonedTimeToUtc } from 'date-fns-tz'
const date = getDatePickerValue() // e.g. 2014-06-25 10:00:00 (picked in any time zone)
const timeZone = getTimeZoneValue() // e.g. America/Los_Angeles
const utcDate = zonedTimeToUtc(date, timeZone) // In June 10am in Los Angeles is 5pm UTC
postToServer(utcDate.toISOString(), timeZone) // post 2014-06-25T17:00:00.000Z, America/Los_Angeles
In your case, the only change is that at the very end instead of calling utcDate.toISOString() you'll call utcDate.getTime().
Note that you'll still want to divide by 1000 if you intend to pass timestamps in seconds rather than the milliseconds precision offered by the Date object.
You can use 'moment' to convert timezone.
1.Create a moment with your date time, specifying that this is expressed as utc, with moment.utc()
2.convert it to your timezone with moment.tz()
For example
moment.utc(t, 'YYYY-MM-DD HH:mm:ss')
.tz("America/Chicago")
.format('l');
Related
When I try to make a post request with React js to a make a reservation the time diminishes by two hours, while in the state it is exactly the time I wanted, meanwhile in the DB it is saved with two hours less. Example I try to save 11 o'clock instead saves 9 o'clock.
This is how format the date and time before passing it to the api call
const booking_date = new Date(year, month, day, hour, minute);
You can use a timestamp to get a more accurate consistent date
const booking_date = new Date(year, month, day, hour, minute).getTime();
Then if you need an actual date string you can convert it back to a date using new Date(). This is likely a timezone issue so a timestamp would mitigate that, along with giving you the extra bonus of being able to send less data in the api call.
Alternatively, if you NEED a string date you can use:
new Date().toUTCString()
which will convert the date to a UTC string that is consistent across the world (it will give you the same value no matter your location) since it uses the standardised UTC timezone.
See more here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
You can use moment.js. If you have a date string then convert it using moment.js before sending the post request or if you do not have any date string, you just need to pick the current date and time means then you can use as like below with the desired format you need. I'd recommend to always use UTC internally, and convert to a timezone only when displaying the date to the user
import moment from "moment";
let date = moment().format('MM-DD-YYYY hh:mm:ss')} // It will return 06-16-2020 08:54:00
Is there some way to find out what is the time zone of a user, in UTC format(like UTC+1, UTC+2,...etc)
What I am trying to accomplish is that after user selects UTC time zone from drop down and selects time and date, I want to show date and time values in his time zone (time zone from browser or system).
So if for example user selects: UTC+2 and 13:00 11-03-2016 and his system time zone is UTC than I want to show in some label: In your time that is: 11:00 11-03-2016 (since the UTC is minus 2 hours comparing to UTC+2)
Does somebody has suggestions on how to accomplish something like this?
Just create new Date object without specifying the time zone - JavaScript will use the browser's time zone and when getting a date, without specifying the time zone, the result is converted to the browser's time zone.
Please review examples on http://www.w3schools.com/js/js_dates.asp
Hope it will help. Handling dates in js and angular is a bit tricky;)
We are using JavaMail API to send calendar entries. But the recipients of Outlook have time zone issues, as meetings show wrong timings. In general our approach is as follows:
First of all we have,
SimpleDateFormat iCalendarDateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
we then use iCalendarDateFormat.setTimeZone(TimeZone.getTimeZone(receiverTimeZone));
Finally, we use Calendar.getInstance() for start and end to manipulate Calendar fields,
and hence we have Date startDate = startTime.getTime();
Date endDate = endTime.getTime();
When we are about to send request as per icalendar specification we have ,
"DTSTAMP:" + iCalendarDateFormat.format(startDate) + "\n" +
"DTSTART:" + iCalendarDateFormat.format(startDate)+ "\n" "DTEND:" + iCalendarDateFormat.format(endDate)+ "\n"
Is this the correct approach?. Please comment.
Thanks
tl;dr
iCalendar format tracks the date-time separately from its intended time zone. You must juggle both parts appropriately.
Always use java.time classes. Never use legacy classes like Calendar & SimpleDateFormat.
Details
Caveat: I have not used iCalendar data before. So I may be incorrect in my understanding.
Looking at pages 31-33 of the RFC 5545 spec, it seems the authors of that spec assume you always want the date-time to be recorded separately from the time zone.
A moment, a point on the timeline, needs the context of a time zone or offset-from-UTC. For example, "noon on the 23rd of January next year, 2021" is not a moment. We do not know if you mean noon in Tokyo Japan, noon in Toulouse France, or noon in Toledo Ohio US — all very different moments, several hours apart.
To provide the context of an offset, a date and time must be accompanied by a number of hours-minutes-seconds such as 08:00. For an offset of zero hours-minutes-seconds, use +00:00.
2021-01-23T12:00:00+00:00
As an abbreviation of an offset of zero, +00:00, the letter Z can be used, pronounced “Zulu”. For example:
2021-01-23T12:00:00Z
But, strangely, the iCalendar spec wants to track the date and the time-of-day separate from the time zone. So this:
2021-01-23T12:00:00
…and a time zone field elsewhere:
America/New_York
And the iCalendar spec opts for the harder-to-read “basic” variation allowed by ISO 8601, which minimizes the use of delimiters. So this:
20210123T120000
For such a string, we must parse as a LocalDateTime. This class represents a date with a time-of-day but lacking any time zone or offset-from-UTC.
DateTimeFormatter f = dateTimeFormatter.ofPattern( "uuuuMMdd'T'HHmmss" ) ;
String input = "20210123T120000" ; // “Basic” variation of ISO 8601 format.
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
To determine a moment, we must apply a time zone. I assume iCalendar uses proper time zone names (Continent/Region format) and not the 2-4 letter pseudo-zones such as PST, CST, IST, and so on.
String zoneName = receiverTimeZone ; // Variable name taken from your code example, though you neglected to show its origins.
ZoneId z = ZoneId.of( zoneName ) ;
Apply the zone to get a ZonedDateTime, a moment, a point on the timeline.
ZonedDateTime zdt = ldt.atZone( z ) ;
Going the other direction, let's start with the current moment.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
And generate string values for iCalendar.
DateTimeFormatter f = dateTimeFormatter.ofPattern( "uuuuMMdd'T'HHmmss" ) ;
String iCal_DateTime = now.format( f ) ;
String iCal_ZoneName = now.getZone().toString() ;
Never use the terrible legacy date-time classes bundled with the earliest versions of Java: Calendar, GregorianCalendar, java.util.Date, SimpleDateFormat, and so on. These were supplanted years ago by the modern java.time classes defined in JSR 310.
Hard to tell without seeing the actual content of your iCalendar file, along with the expected start and end datetime with timezone information but you seem to be generating the DTSTART in floating time (datetime with local time). Although your code sample seems to imply that you have access to the recipient's timezone (receiverTimezone), this is a very fragile approach.
Instead, you should use either the datetime with UTC time or the datetime with local time and timezone (where the timezone does not have to be the receiver timezone).
If the event is not recurring, the most simple approach is to use datetime with UTC time.
See https://www.rfc-editor.org/rfc/rfc5545#section-3.3.5 for the definition of each format.
I had same problem, for which I struggle lot. So below are my findings:
Outlook works smoothly with UTC Timezone. If we set date & time with UTC Timezone then outlook automatically converts this UTC Time into user corresponding Timezone. We will have to use 'Instant' object for DTSTART:, DTEND: and for DTSTAMP(Optional but recommended) also.
Quick Test just use "DTSTART:"+Instant.now() in ical String.
And in Java 8 for getting UTC Time java time API provides Instant.now() through which you can get your system time in UTC format. Java 8 also provides method like
a. Instant.ofEpochMilli() - This returns Instant which can directly use in ical Sting.
b. new Date().toInstant() Which returns UTC Instant object.
There are few scenarios where input date and time sources are different:
If you are fetching Date and Time from database then in this case database is not storing Timezone its only saving Date & Time. So first convert the Date & Time in that Timezone in which it was saved in database, in my case I was storing Date & Time after converting in 'EST' Timezone and Date value was of EST but time zone was not there in DB. So while fetching Date & Time value from DB I have appended Timezone in the Date value and then further converted to EPOC time using below method
public static long getEpocTimeWithTimezone(Date date) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter dateTimePattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse(simpleDateFormat.format(date), dateTimePattern);
long epochInMilliSeconds = dateTime.atZone(ZoneId.of("America/New_York")).toEpochSecond() * 1000;
return epochInMilliSeconds;
}
Then Just Use as below code for ical String:
Instant startDt = Instant.ofEpochMilli(getEpocTimeWithTimezone(//pass your date here
)).truncatedTo(ChronoUnit.MINUTES);
Now set this Instant object(startDt) directly to "DTSTART:":
"DTSTART:"+startDt+"....then in same fashion "DTEND:" also.
In second scenario you have Date with Timezone (make sure after conversion you did not loses your actual Timezone, Like in 1st scenario after saving Date in DB we actually lost Timezone but it was showing Timezone IST that was dummy so be careful about this)
So in this case just assume myDateObject is Date object. So just get the Instant (which
will be in UTC) object from myDateObject by using toInstant() of Date class.
Instant startDt = myDateObject.toInstant().truncatedTo(ChronoUnit.MINUTES);
I am using .truncatedTo(ChronoUnit.MINUTES); because if we will not use this then
we might get some extra min or second in Meeting invite Time section.
So the final String for outlook mail should be some like:
.
.
.
"BEGIN:VEVENT\n"+
"DTSTART:"+startDt+"\n"+
"DTEND:"+endDt+"\n"+
.
.
.
VVI Note: Since Z is representation of UTC time zone, So just adding Z in the last of Time will not be UTC zoned Time, You will have to convert the Date & Time then only accurate time will come on Outlook. For verifying your Time is in UTC format or not just save the .ics attached file (which you got in Email) in local and check Date & Time are coming as DTSTART:2020-05-15T13:57:00Z or not If not then you are not converting the Date correctly in UTC.
new Date(moment().year(), moment().month(), moment().day(), vm.newHearing().HearingTime().split(":")[0], vm.newHearing().HearingTime().split(":")[1]).toLocaleString()
The client side value for a date column is 11/5/2013 10:15:00 AM. The time is selected from HTML5 time input control.
When I check in database after saving the entity, it shows me incorrect time value:
11/5/2013 3:15:00 PM
It appears that you are using moment.js, which is fine except you aren't using it properly
Try this instead:
moment(vm.newHearing().HearingTime(), "HH:mm").toISOString()
That will pass the selected time, on the current day, from the user's local time zone, converted to UTC time and in ISO format.
Now that might not be exactly what you want to do. Depending on your requirements, you might instead want this:
moment.utc(vm.newHearing().HearingTime(), "HH:mm").toISOString()
Which is almost the same thing except that it assumes the input time is already in UTC.
Or you might want this:
moment(vm.newHearing().HearingTime(), "HH:mm").format("YYYY-MM-DDTHH:mm:ss")
This one doesn't try to convert to UTC at all.
For all choices, I emit the date string in ISO8601 format. Since you are sending it back to the server, this is the best choice. When you used toLocaleString, that generates a format that is appropriat for display only.
I am working in MVC4 project where i am facing problem with time.Actually my project requirement is to show all time used in application according to Brazil time.So i have used GETUTCDATE() for saving time in application.
Now i want to check if DST is on according to time i saved..i mean central time. How do i check this.
I have search on net and found one solution
DECLARE #IsDST BIT;
SET #IsDST = CASE WHEN DateDiff(hour, GetDate(), GetUTCDate()) = 4 THEN 'True'
ELSE 'False' END;
SELECT GETDATE() AS GETDATE,
GETUTCDATE() AS GETUTCDATE,
#IsDST;
But when i try to run this script,it return false ??
But as per DST calculation,it always starts from 2nd Sunday of March and ends on 1st Sunday of November.
Then it should return true ,that DST is on.
Am i doing right or is there another better approach to check if DST is on central time,so that i can show brazil time according to DST
Well, this particular code doesn't work for detecting DST in Brazil, because it just measures the difference right now between local time and UTC, checking for 4 hours difference or not.
Most of Brazil is 3 hours behind UTC in the standard time, and 2 hours behind UTC in the daylight time. So this code probably won't work for you. You can read more in this Wikipedia article.
Daylight Saving Time is very different all over the world, so if you intend to use this approach then you will have to modify your code to match the time zone of the server that it's running on.
Personally, I would recommend not doing this in SQL at all. Time zone conversions aren't really the realm of the database. They work much better in application code. You should work with UTC in your database, and convert it to Brazil or whatever time zone you require in your application.
Since you said this was an ASP.Net MVC4 application, I recommend you either use the .net TimeZoneInfo class, or use the excellent Noda Time library to do your conversions in your .Net code.
Using TimeZoneInfo:
DateTime utcDT = // ... your UTC value returned from the database
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById(
"E. South America Standard Time"); // Brazil
DateTime brazilDT = TimeZoneInfo.ConvertTimeFromUtc(utcDT, tz);
Using Noda Time:
DateTime utcDT = // ... your UTC value returned from the database
Instant instant = Instant.FromDateTimeUtc(utcDT);
DateTimeZone tz = DateTimeZoneProviders.Tzdb["America/Sao_Paulo"]; // Brazil
ZonedDateTime brazilZDT = instant.InZone(tz);
DateTime brazilDT = brazilZDT.ToDateTimeUnspecified();