Formatting a date to the senders local time - javascript

I am having a hard time taking a UTC Date string with an offset and adjusting the time to the users local time exactly. I receive a date on our server say: 2017-06-21T20:26:28.744Z and I need to turn it into a timestamp of the senders local time. For the sake of this example lets say the offset is 6 hours.
I know that this is probably wrong and that the z portion explains what the offset really is.
I need to turn 2017-06-21T20:26:28.744Z into 2017-06-21T14:26:28 using moment.
Doing this seems to give me the UTC portion of the string and chops off the offset. I need to use the offset to adjust the hours/ minutes back
moment
.utc('2017-06-21T20:26:28.744Z')
.local()
.format('YYYY-MM-DDTHH:mm:ss')
// 2017-06-21T20:26:28"
// I need 2017-06-21T14:26:28

You can use utcOffset
Setting the UTC offset by supplying minutes. Note that once you set an offset, it's fixed and won't change on its own (i.e there are no DST rules). If you want an actual time zone -- time in a particular location, like America/Los_Angeles, consider moment-timezone.
If the input is less than 16 and greater than -16, it will interpret your input as hours instead.
Here a working sample:
console.log( moment
.utc('2017-06-21T20:26:28.744Z')
.utcOffset(-6)
.format('YYYY-MM-DDTHH:mm:ss') );
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
If you want to use moment-timezone, you can use tz() method:
console.log( moment
.utc('2017-06-21T20:26:28.744Z')
.tz('America/Chicago')
.format('YYYY-MM-DDTHH:mm:ss') );
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.13/moment-timezone-with-data-2012-2022.min.js"></script>

Related

How to subtract the time based on the timezone offset

I tried looking for an answer but could not find a particular answer which does with Timezone offset. Hence, posting the same really sorry if there are any answer present already.
I have a requirement in the project where I need to convert the time to UTC or GMT based on the time specified by the user and timezone offset value provided by the user. Basically, the user provides his local time and timezone offset value according to his local time. I need to convert that into UTC/GMT time.
I am using the Node.js and following is the data which is available in the Node.js Backend:
Time: 2020-11-05T15:00:00.000Z
Timezone offset value: +02:00
As the timezone offset value is +02:00 I need to subtract it from the time to convert it into the UTC format. so I can get the time as: 2020-11-05T13:00:00.000Z. I using the moment-js as well. Can someone please help me how can achieve this using the Node.js or using the Moment.js?
If the offset takes daylight saving time into account you should be able to do:
const the_date = '2020-11-05T15:00:00.000';
const offset = 2;
const utc_time = moment.utc(the_date).subtract(offset, 'hours');
It's not clear which way you are trying to convert. If you are converting from UTC to a fixed offset, you can use the utcOffset function, like this:
const m = moment.utc('2020-11-05T15:00:00.000Z').utcOffset('+02:00');
m.format(); //=> "2020-11-05T17:00:00+02:00"
Or - if you were trying to convert from +02:00, then you would include that offset in the input instead of the Z (Z means UTC). You would then just call the utc function, like this:
const m = moment('2020-11-05T15:00:00.000+02:00').utc();
m.format(); //=> "2020-11-05T13:00:00Z"
However you should be aware that an offset is not the same as a time zone. A time zone can have more than one offset, one of which will apply at a given point in time. Those offsets can change due to daylight saving time and for changes in standard time. Thus, asking a user to pick "his timezone offset value according to his local time" is problematic - as you may be applying that offset to the wrong point in time. See "Time Zone != Offset" in the timezone tag wiki for further details.
You should also understand Moment's project status, and possibly choose a different library.
After some more research and trying, I was able to convert it. Posting the answer in addition to Christians response (https://stackoverflow.com/a/64701083/7584240) so if anyone is looking for the answer they will have another option:
var moment = require('moment');
var time = "2020-11-05T15:00:00.000Z";
var timeoffset = "+02:00";
time = moment.utc(time).local().format('YYYY-MM-DDTHH:mm:SS.000');
time = moment(time, 'YYYY-MM-DDTHH:mm:ss.000').subtract(timeoffset).format('YYYY-MM-DDTHH:mm:ss.000') + 'Z';

Unknown date format /Date(1427982649000-0400)/

I need to display on the screen some date values but I'm receiving them in a format that I don't know. Does anybody know what format is this and how to convert them?
For example, I'm getting this:
/Date(1427982649000-0400)/
In the database is stored as
2015-04-02 09:50:49.000
I really don't know where to start looking at.
It's a unix timestamp in milliseconds, followed by a timezone (shift in hours differing from UTC).
So, it's UTC -4 hours, 1427982649 seconds after the 1st January of 1970.
Nice little tool for checking unix timestamps : http://www.unixtimestamp.com/index.php (don't forget to convert your milliseconds to seconds before posting them there)
/edit: To add some additional information - the "timezone shift" seems to be following RFC822 (and/or probably some other RFCs), that -0400 can be explained by the syntax "+/-HHMM" specified there, so to be exact it means -04 hours, 00 minutes.
The actual time and date gets converted into the milliseconds, and it follows the Unix time January 1st, 1970.
Because it is the date when the time for the Unix computer started.
But you can convert the milliseconds into the actual time by using some loops or conversions according to that time.
Does anybody know what format is this and how to convert them?
It seems that "/Date(1427982649000-0400)/" is a time value in milliseconds followed by an offset as ±HHmm. To convert that to a Date, use the time value adjusted by the offset.
Assuming the offset uses the typical sign convention, then a positive offset needs to be subtracted and negative offset added to get the correct UTC value, then something like the following should suit:
var s = '/Date(1427982649000-0400)/';
// Get the number parts
var b = s.match(/\d+/g);
// Get the sign of the offset
var sign = /-/.test(s)? -1 : +1;
// Adjust the time value by the offset converted to milliseconds
// and use to create a Date
var ms = +b[0] + sign * (b[1].slice(0,2)*3.6e6 + b[1].slice(-2)*6e4);
console.log(new Date(ms).toISOString()); // 2015-04-02T17:50:49.000Z
In your example, "2015-04-02 09:50:49.000" does not have a timezone, so it represents a different moment in time for each timezone with a different offset. If that is the actual value stored in the database, then I guess the missing timezone is UTC-0800. It is much better to store the values using UTC and to include the offset, then the host timezone is irrelevant.
Things are complicated here because ECMAScript timezone offsets are the opposite sign to the normal convention, i.e. positive for west of Greenwich and negative for east. If that convention is applied, then "/Date(1427982649000-0400)/" converts to 2015-04-02T09:50:49.000Z, which may be what you're after.
If that is the case, just change the sign in the line:
var sign = /-/.test(s)? -1 : +1;
to
var sign = /-/.test(s)? +1 : -1;

moment.tz issue with setting a "Etc/GMT[+|-]HH:MM" timezone

I've been banging my head on this for over a day, gone into the source code, and this looks to be an issue with the awesome javascript moment.tz library:
Whenever I pass in a timezone identifier of "Etc/GMTtime-value", the moment.tz object returned comes back with what I believe to be an format("Z") value as it is multiplied by -1.
Example:
var pacificTime = moment.tz("2016-09-29 21:00:00","America/Los_Angeles");
pacificTime.format("YYYY-MM-DD HH:mm:ss Z z");
output: "2016-09-29 21:00:00 -07:00 PDT"
All is as expected here.
Now, using the same time zone (GMT-7):
var GMT_minus_7 = moment.tz("2016-09-29 21:00:00","Etc/GMT-7");
GMT_minus_7.format("YYYY-MM-DD HH:mm:ss Z z");
output: "2016-09-29 21:00:00 +07:00 GMT-7"
The bold faced value is always the negative value of what I believe it should be: Passing in "Etc/GMT+5" returns a "-5:00" value.
This is causing me a headache, as the web page I'm working with has records with date/time records an integer "GMT offset" value which I simply turn into "Etc/GMT" + offset_value and pass into moment.tz to do a time zone conversion. I then need to do further manipulation on the value (adding days, displaying that "Z" formatted value, etc.) but this issue has impeded further work.
Is this a defect with moment.tz parsing the "Etc/GMT" timezone values, or am I missing something fundamental about time zone formatting?
The identifiers in the IANA database such as Etc/GMT-7 have their offset inverted intentionally. This is part of the design of this style of identifier. See the note in Wikipedia on this, and in the tz database source itself. (Basically, it stems from the need to be backwards compatible with older POSIX standards in certain environments.)
However, in the case of Moment.js, you do not need to use these at all if you are working with a fixed time zone offset. In fact, you don't need the moment-timezone extension at all.
// the parseZone method will retain the offset provided
var a = moment.parseZone("2016-09-29 21:00:00 -07:00");
// or, you can set the offset explicitly like this:
var b = moment.utc("2016-09-29 21:00:00").utcOffset("-07:00", true);
// or like this if you prefer:
var c = moment.utc("2016-09-29 21:00:00").utcOffset(-7, true);
For b and c, note that the true parameter is required to retain the given local time. Also note that I use moment.utc(...) to initially parse the string. It would also work with just moment(...), but then it's possible that a DST transition in the local time zone could interfere with the interim value.
Also, make sure you recognize that America/Los_Angeles alternates between -8 and -7 depending on whether DST is in effect or not. That is why you would need moment-timezone to supply the rules for when to switch between offsets.

Convert hour to date time without adding +1

Hi im using moment js to convert this string 20:00 I tried:
var a = moment("20:00", "HH:mm")
console.log(a.format()) // 2016-09-08T20:00:00+01:00
the problem when I store in mongodb it become
2016-09-10T19:00:00.000Z
I want to store 2016-09-10T20:00:00.000Z
anyway can explain why please ?
When you say that you want to store 2016-09-10T20:00:00.000Z what you are saying is that you want to assume that your date and time is UTC.
To assume that the date you are parsing is a UTC value, use moment.utc
var a = moment.utc("20:00", "HH:mm")
console.log(a.format()) // 2016-09-08T20:00:00Z
Note that when you parse a time without a date, moment assumes the current date. This may not be the behavior that you want.
I'm also not sure if you want a UTC date (which is what you are saying), or a local date without an offset indicator. If you want a local date without an offset indicator, simply use a format without an offset:
moment.utc("20:00", "HH:mm").format('YYYY-MM-DDTHH:mm:ss.SSS')
"2016-09-08T20:00:00.000"
If you are dealing with local dates that do not have a time zone association, I recommend using moment.utc to parse, as this will ensure that the time does not get shifted to account for DST in the current time zone.
For more information about how to parse dates into the time zone or offset that you would like in moment, see my blog post on the subject.
This it how it should look:
var a = moment("20:00", "HH:mm")
console.log(a.utcOffset('+0000').format())
<script src="http://momentjs.com/downloads/moment.min.js"></script>
Doe, the problem is that you are using timezones when you create the date.
MomentJS uses your current timezone automatically.
Mongo however saves the time as it would be in another timezone.
Therefore, if you want the two strings to format the same way, you need to set the timezone.

Extracting utcOffset from an ISO String with Moment.js

Using moment.js, I'm attempting to extract the offset from an ISO date string so I can use the offset later when formatting an epoch timestamp to ensure the conversion of the timestamp is in the same timezone.
Even though the offset in the string is -0400, the result is always 0;
var currentTime = "2015-03-18T16:10:00.001-0400";
var utcOffset = moment(currentTime).utcOffset(); // 0
I've attempted to use parseZone() as well without success. Is there a way to extract -0400 from the string so I can use it while formatting another time?
Thanks for the help!
KC
The correct way to extract the offset is indeed with parseZone
var currentTime = "2015-03-18T16:10:00.001-0400";
var utcOffset = moment.parseZone(currentTime).utcOffset();
This should result in -240, which means 240 minutes behind UTC, which is the same as the -0400 in the input string. If you wanted the string form, instead of utcOffset() you could use .format('Z') for "-04:00" or .format('ZZ') for "-0400".
The form you gave in the question just uses the computer's local time zone. So it is currently UTC+00:00 in your time zone (or wherever the code is running), that would explain why you would get a zero. You have to use parseZone to retain the offset of the input string.
Also - your use case is a bit worrying. Remember, an offset is not the same thing as a time zone. A time zone can change its offset at different points in time. Many time zones do this to accommodate daylight saving time. If you pick an offset off of one timestamp and apply it to another, you don't have any guarantees that the offset is correct for the new timestamp.
As an example, consider the US Eastern time zone, which just changed from UTC-05:00 to UTC-04:00 when daylight saving time took effect on March 8th, 2015. If you took a value like the one you provided, and applied it to a date of March 1st, you would be placing it into the Atlantic time zone instead of the Eastern time zone.

Categories

Resources