Dates (Assigning them depending on region) - javascript

var d = new Date();
"**Zone** - `" +
d.toTimeString().replace(/\d+:\d+:\d+\s+/, '').replace(/[G][M][T].\d+/, '') +
"` **Time** - " +
"`" + d.toLocaleTimeString() +
"` **Date** - " + "`" +
d.toLocaleDateString() + "`"
This is a string of mine which tells me the region, time and date. I am using it on a discord bot and am attempting to make them be different depending on the user's region. I'm not sure how to accomplish this, but for visual example...
The code stated above returns me -
Zone - (AUS Eastern Standard Time) Time - 16:49:28 Date - 2018-5-18
which I am satisfied with, however, for a test I got a foreign friend to hop on and it sent the same thing when what I am trying to make the result be is their region so...
Zone - (AMERICA Western Standard Time) Time - 02:29:09 Date - 2018-5-18
Anybody have any ideas?
EDIT: Within a new project of mine, I discovered the user of Intl.DateTimeFormat() which essentially returns an Array. There is an instance method for this function known as .resolvedOptions(), returning an object that has many values within. I simply went ahead and added .timezone which returned something similar to "Australia/Queensland".
var region = Intl.DateTimeFormat().resolvedOptions().timeZone;

I am assuming this code is run in a browser, and not in a server.
You cannot depend on d.toTimeString() and cutting out the timezone part to find a timezone, toTimeString can return different formats on different browsers. The specs has left the formatting to browser vendors.
You can get the timezoneOffset and map it to the timezone name, but wait, there is an issue. This may conflict with Day Light Savings time setting for regions. So you will need a historical set of data for Daylight Savings time all over world.
If you really want to do this, use moment with timezones, which can do the lookup for you and they have already created all mappings including DST for you.

Related

MomentJS, how to ignore user's local timezone, and use

Here's the scenario:
1- User opens the website, and enters 07:00 am using a dropdown field, which will give me this :
// 1578600000000 => Save to DB
// Fri Jan 10 2020 07:00:00 GMT+1100 (Australian Eastern Daylight Time)
The user himself is in Sydney, which means his local clock is on GMT+1100
However, he wants to represent this time as Asia/Tehran time, because that's where he's going to be tomorrow. So essentially, he wants me to completely ignore his local time and see him as if he's in Asia/Tehran. So when he's in Tehran tomorrow, he can see his calendar has 07:00am.
On the other hand, are the people all over the world who will see his available time, let's say from Australia/Perth.
I thought something like the below work, as per momentJS documentation, but it doesn't.
First, convert the timezone to Asia/Tehran, which is the user's desired place:
const desiredTimeZone = 'Asia/Tehran';
let OriginalDesired = moment.tz(1578600000000,desiredTimeZone);
Then, when representing it to the people in Australia/Perth make sure it's in their timezone
const PerthTimeZone = 'Australia/Perth`; // this is dynamic, can be anything
OriginalDesired.clone().tz(PerthTimeZone);
I naively thought this should work. But I noticed the original timestamp 1578600000000 is a UTC timestamp, meaning it's not really 07:00am, it's actually 20:00pm, because Javascript
has subtracted 11 hours, which is the very original user's local timezone's offset, from the user entry.
I managed to work around it by adding and subtracting the offset in a dramatic way, but it only works in one scenario.
const originalTime = 1578600000000;
const LocalAdjustment = moment(originalTime).tz("Australia/Sydney").utcOffset() * 60000;
const DesiredAdjustment = moment(originalTime).tz("Asia/Tehran").utcOffset() * 60000;
const newUTC = originalTime + LocalAdjustment - DesiredAdjustment;
And when representing this to the user's in Tehran
moment(newUTC).tz("Asia/Tehran").format('hh:mma'); // 07:00am.
I know this is probably stupid and obviously only works in one scenario, but is this the right path that I'm going? or is there an easier way?
By the way, all the calculations are on my server, which is 'UTC'.
You said:
1- User opens the website, and enters 07:00 am using a dropdown field, which will give me this : // 1578600000000 ...
You've already lost. If the local time zone is not relevant, then don't write code that assumes that it is.
In other words, you probably have something along the lines of:
moment("2020-01-10 07:00")
Instead you should have something like:
moment.tz("2020-01-10 07:00", "Asia/Tehran")
Or rather, you should simply send "2020-01-10 07:00" and "Asia/Tehran" to your database, then later retrieve them and pass them to moment-timezone when you need to know what moment that represents.
As to your other approach, it's generally not a good idea to add or subtract time zone offsets from timestamps. Unix timestamps are inherently UTC based. Adding or subtracting will produce a different moment in time, not adjust for time zone.
Consider that there's also a slim (but not impossible) chance that the offsets returned by your code are incorrect, as they would have to be shifted before being looked up. In other words, Tehran was at UTC+3:30 on the date in question, so the timestamp passed would have to be adjusted by 3 hours 3 minutes before being passed to the moment constructor. This leads to circular logic, and is difficult to resolve. It will show up for timestamps near transitions (either for DST, or for changes to standard time for a particular time zone).

Date and time parsing in JavaScript

I have a question that I am trying to solve for whole day.
I have Date and Time from Oracle DB that is shown on html page. I have jstl date formatter that has special pattern to show it. Let's take an example 09.05.2017 17:35 +0500 and pattern MM.dd.yyyy HH:mm Z. And I am getting it as String with jQuery . The first case: how to convert it to Date type without any changes. I tryed var date = new Date('09.05.2017 17:35 +0500') but if I have another time zone I'll recieve another UTC and time(hour) or maybe month etc.
Second: how to convert this time to UTC+0300.
I know one solution of this cases, but I think it's not easy. As I have constant pattern of Date, I can always parse the string and to write huge logic for solving second case. I am bad in JS and will be grateful for solution.
Regarding the parsing question, that is answered at Why does Date.parse give incorrect results? The bottom line is that you should parse the string manually and not rely on the built-in parser. A library can help, but if you only have one or two formats to deal with, writing your own parser isn't too difficult.
As for presenting time in a particular timezone, the same advice applies. If you always want UTC+0300, then start by knowing that javascript Dates are always UTC internally and have UTC methods to access those values. So you just change the UTC time by the required offset and format the date as required.
For formatting, see Where can I find documentation on formatting a date in JavaScript?
An example of adjusting the timezone:
// Return a string for UTC+0300 for the supplied date
// in dd-mm-yyyy hh:mm:ss format
function getUTC03(date) {
// Helper to pad with leading zero
function z(n){return ('0'+n).slice(-2)}
// Copy the date so don't affect original
var d = new Date(+date);
// Set UTC time to required offset
d.setUTCHours(d.getUTCHours() + 3);
// Format using UTC methods
return z(d.getUTCDate()) + '-' +
z(d.getUTCMonth()+1) + '-' +
d.getUTCFullYear() + ' ' +
z(d.getUTCHours()) + ':' +
z(d.getUTCMinutes()) + ':' +
z(d.getUTCSeconds()) + ' ' +
'+0300';
}
console.log('Currently at +0300 it\'s ' + getUTC03(new Date()));
However, many places observe daylight saving. To adjust for that, a library is helpful. You just need to provide a location for which the offset can be determined for any particular date and time. Again, there are many questions here about that too.

MomentJS gets different UNIX timestamps on different platforms

I have encountered interesting problem:
I have an timestamp with value 1500400800
I want to get staart of day and end of day of this timestamp. By using moment.js I have written this code:
let timestamp = 1500400800;
let momentDate = moment.unix(timestamp);
let start = momentDate.startOf('day').unix();
let end = momentDate.endOf('day').unix();
console.log(timestamp + " " + start + " " + end);
My own PC returns for 1500400800 these values:
1500400800 1500400800 1500487199
But virutal machine in my hosting returns this:
1500400800 1500336000 1500422399
They are different. There are six hours difference between two platforms.
How to make virtual hosting machine get timestamps just like my local PC gets?
Moment assumes time relative to the time of the local system. Your virtual server either has an incorrect clock or is located in another timezone. You can either work exclusively in UTC by telling moment to convert to UTC, or you might look into moment-timezone which is an extension of moment built specifically for working in multiple timezones.

How to convert UTC date/time to EST date/time

I'm using the following code to get the current UTC time in the correct format, but the client has come back and asked that the timestamp now be in EST instead of UTC. I have searched Google and stackoverflow, but can't find an answer that works with my existing code.
var currentdate = new Date();
var datetime = currentdate.getFullYear() + ":"
+ ("0" + (currentdate.getUTCMonth()+1)).slice(-2) + ":"
+ ("0" + currentdate.getUTCDate()).slice(-2) + ":"
+ ("0" + currentdate.getUTCHours()).slice(-2) + ":"
+ ("0" + currentdate.getUTCMinutes()).slice(-2) + ":"
+ ("0" + currentdate.getUTCSeconds()).slice(-2);
What we are trying to do is set a consistent timestamp to EST regardless of where the browser is located in the world, hence the use of the UTC time originally.
Thanks!
A few things...
The term "EST" can be used for either Eastern Standard Time in North America, or Eastern Standard Time in Australia. Most time zone abbreviations are not unique, so you should be more specific.
EST also does not define a time zone in its entirety. It only defines part of the time zone that is used during the winter months. The other half is called Eastern Daylight Time, abbreviated EDT. Your client probably meant "Eastern Time", which would need to take both into account.
The typical way to define time zones is as an identifier from the IANA time zone database. You can read more about it in the timezone tag wiki. For example, if your client meant Eastern Time in the United States, then your time zone is "America/New_York".
JavaScript inherently doesn't know anything about time zones, other than it's own and UTC. (The link that bjb568 gave does not handle daylight saving time properly.) In order to work with them on the client, you will need to use one of the libraries I list here.
Your current code is a bit strange in terms of output. Usually colons are used for separating only the time, and you are using them for all parts. Anyway, it's not converting anything, it's just outputting UTC.
You might do well with a library like moment.js and it's moment-timezone add-on. For example:
moment().tz("America/New_York").format("YYYY-MM-DD HH:mm:ss")
The following answer (copied from this link on this site) worked very well for me. It easily and correctly converted the following Zulu time (which is same as UTC) "2014-10-09T20:30:54Z" to South African time.
var tmpDate = New Date("enter any valid Date format here")
The javascript Date() function will automatically convert it to your local time.
Example:
var tmpDate = new Date("Fri Jul 21 02:00:00 GMT 2012")
alert(tmpDate);
//Result: Fri Jul 20 22:00:00 EDT 2012
Below line will work:
console.log(moment().tz("America/New_York").format("YYYY-MM-DD HH:mm:ss"))

Using timezones with moment.js fromNow() or from()

I want to show users how long has been elapsed since they performed an action.
The date+time of the action happening is stored on the server, in the server's timezone. That's what's causing the trouble, since if the user's computer's timezone is 12 hours ahead of the server's timezone, then if the user adds something right now, moment.js will show '12 hours ago' as the output of fromNow() rather than just now.
To try to solve this, I'm trying the following method:
var actionTime = moment( action.timeStamp);//time of when user performed action
var serverTime = moment().zone('-07:00'); //current server time
console.debug( serverTime);//outputs Wed Sep 11 2013 15:19:51 GMT-0700
var timeAgo = serverTime.from( actionTime);
But despite of all this, timeAgo still shows the difference between the client's timezone and the server's timezone (i.e showing '12 hours ago' instead of 'now');
Anyone know how to fix this or what I'm doing wrong?
Ideally, you would want to pass a UTC timestamp from your server to the client. That doesn't mean you have to switch your whole server over to UTC, it just means that you would convert from the time in your database to UTC on the server before sending it over the web. Sure, it would be even better if you actually stored times in UTC, but you said you aren't in a position to make that sort of change right now. But let's just work off the assumption that you can't change anything at all on the server.
We'll also assume that your server is fixed to the UTC-07:00 offset. In real life, this would only be true for places like Arizona that don't follow daylight saving time. So if you are in Los Angeles and are in Pacific Time, then some of your data is based on UTC-07:00, but some of it is based on UTC-08:00. That requires a lot more work if you want to do it in JavaScript.
Let's also assume that the input is already a string in ISO8601 format. (If it's not, then let me know and I will adjust this code.)
var s = "2013-09-11 18:00:00"; // from action.timeStamp
var actionTime = moment(s + "-07:00", "YYYY-MM-DD HH:mm:ssZ");
var timeAgo = actionTime.fromNow();
The reason your other code didn't work is because in the first line, you are affected by the time zone of the browser. The zone setter in the second line just changes the zone for formatting, not changing the actual moment in time.
Also, when you dump a moment to the console for debugging, make sure you format it for output. Otherwise you are just looking at its internal property values, which may or may not make sense directly.
I have solved it in a different way, maybe this option was not possible back when the question was asked, but might be easier now.
I used moment-timezone.js (which requires moment.js 2.6.0+).
I set the default timezone to my server's timezone like this:
moment.tz.setDefault("America/New_York"); // "America/New_York" in my case
and then just use it normally. fromNow() will use the timezone in the client to calculate the time that has passed since that moment.
moment(myDatetime).fromNow();
i had the same issue and used the above comments to modify my code. I did the following to get it resolved:
transform(value: string) {
var time = moment(value).utc();
return moment(time, "YYYYMMDD").fromNow();
}
I was missing the .utc() to convert it before I applied the .fromNow()
Things to note this is being used within a Pipe for Ionic 3 and the above code is from the pipe logic.

Categories

Resources