Date.toLocaleDateString format issues - javascript

The Date.toLocaleDateString() doesn't work in my Windows 10 laptop running nodejs (v10.15.0) as server for a discord.js bot. It shows mm/dd/yyyy instead of dd/mm/yyyy.
I'm using 'en-GB' as the first argument for locale, and second argument for the format I want to achieve (dd/mm/yyyy). And in https://js.do/ , it displays dd/mm/yyyy, but somehow in my laptop it shows as mm/dd/yyyy, and they're both using the same code except for "document.write", I used "console.log" for displaying the result.
let d1 = new Date();
let options = {
year: 'numeric',
month: '2-digit',
day: '2-digit'
};
document.write(d1.toLocaleString('en-GB', options)); // console.log in my laptop
I would expect it to be dd/mm/yyyy format because it's in 'en-GB' locale, instead of the mm/dd/yyyy format.
What is the problem? Is it because of nodejs? or the js.do website? As discussed in this thread: Date.toLocaleDateString() not working on Nodejs v10.14.2 , but I think the issue is slightly different.

Apparently, nodejs by default only contains the en-US locale, as stated here, hence the mm/dd/yyyy format.
I followed the advice by targos in that issue to install the full-icu module.
After installing it, I ran npm install because of this, then I saw this in the command line:
For package.json:
{"scripts":{"start":"node --icu-data-dir=node_modules\\full-icu YOURAPP.js"}}
And edited my start script accordingly, and it produces the desired result of dd/mm/yyyy.
Huge thanks to #quirimmo helping me in the comments of my question !

I was able to recreate this issue, try dateformat if your code allows.
$ npm install dateformat
var dateFormat = require('dateformat');
let d1 = new Date();
console.log(dateFormat(d1, "GMT:dd/mm/yyyy"));

Related

Convert CST/CDT to UTC Javascript

I have time in string format, which is local time in CDT or CST (Depending upon if daylight saving is going on or not).
Ex-
2021-08-19 15:55:40
So its just string data, there is no indication of tz, I want to convert this local time to UTC.
What can be the best way to do that?
Is there an already existing npm package that can identify and convert automatically?
Code that I'm currently trying to use:
As a first step I am trying to convert DateTime to ISO, which can be converted to UTC easily
const { DateTime } = require("luxon");
var overrideZone = DateTime.fromSQL("2021-05-15 23:10:23", { zone: "America/Mexico_City" });
console.log(overrideZone.toISO()) //=> '2021-05-16T11:10:23.000-05:00'
It's giving me date as 16thMay, But Clearly I mean 15th May 23:10 (11:10 PM) not 16th.
I don't know whats wrong in my code
You could try using the DateTime.fromFormat() function to parse the date string, using a format of 'yyyy-MM-dd HH:mm:ss'.
You can convert the DateTime timezone to UTC using the setZone() function. We'd set the zone to 'UTC' to convert to UTC time.
NB: The working fix here is to upgrade from Node 10.24 to at least Node 12.x
let { DateTime } = luxon;
const dateStr = '2021-05-15 23:10:23';
const zone = 'America/Mexico_City';
const dt = DateTime.fromFormat(dateStr, 'yyyy-MM-dd HH:mm:ss', { zone });
const utcTime = dt.setZone('UTC');
console.log('Local time (Central):', dt.toISO());
console.log('UTC time:', utcTime.toISO());
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.0.1/luxon.min.js" integrity="sha512-bI2nHaBnCCpELzO7o0RB58ULEQuWW9HRXP/qyxg/u6WakLJb6wz0nVR9dy0bdKKGo0qOBa3s8v9FGv54Mbp3aA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Running the same code using Node.js 14.15.5 and luxon 2.0.2 on Windows 10.0.19043.0 gives the result:
Local time (Central): 2021-05-15T23:10:23.000-05:00
UTC time: 2021-05-16T04:10:23.000Z
So it may be due to a difference in environment. Have you tried using a later version of Node.js?
Using the node:10.24 Docker image I get the following output
Local time (Central): 2021-05-16T11:10:23.000-05:00
UTC time: 2021-05-16T16:10:23.000Z
So it looks to me like a Node.js version issue. I would suggest trying a later Node.js release. I've tried node v12.16.1 and I get the correct output. So I would suggest trying at least node v12 to resolve your issue.

How to get the day name from the date string regardless of user's timezone?

Given a date (without time) e.g. 2021-08-11, how could I get its day name (e.g. Wednesday) regardless of the user's timezone?
Note that trying to use:
new Date("2021-08-11").toLocaleString('en-AU', { weekday:'long' })
or date-fns's format:
format(new Date("2021-08-11"), "EEEE")
results in the wrong day (Tuesday) if the user's timezone is GMT-7, for example.
You can use date-fns-tz as suggested by the other comment. It interally uses Intl. If you only care about getting the day you can just use Intl directly:
let formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'UTC',
weekday: 'long',
});
formatter.format(new Date("2021-08-11")) // outputs: "Wednesday"
I would recommend that you also format your dates to ISO i.e. "2021-08-11T00:00:00.000Z" as the Z at the end will ensure that the date is parsed in UTC before formatting.
I haven't surveyed the latest data-fns. But when I used it a couple of years ago, it didn't have a timezone support. Since the Date class does not keep the timezone information internally, it causes some problems when the location of time acquisition is different from where it is used. See this stackoverflow post for details.
There are some libraries available to solve this problem. Since you are using date-fns you might want to try date-fns-tz.

Changing Date time zone in Javascript?

I have a date in UTC format `2020-06-19T03:55:12.000Z. Now i am converting into date of US timezone as
let syncDate = moment(date, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]')
.subtract(7, 'hours')
.format('YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
This gives me a date 7 hours behind which is date of US. But i want a date in below format
2020-06-18T21:00:24.523-07:00
Here if we can see the hours are defined as -7 so please guide how can we achieve the same ?
You can't extract a timezone out of your date because there is no timezone information in it. You said "I am converting into a date of US timezone as" But you didn't. You just reduced it for 7 hours. The timezone is still UTC.
You should use moment-timezone (not handling things the hard way and manually as #GetSet said). Here the solution:
const moment = require('moment');
const tz = require('moment-timezone');
let date = moment('2020-06-19T03:55:12.000Z');
let syncDate = date.tz('America/Los_Angeles')
console.log(syncDate.format());
But, I suggest you use Day.js. The code will be:
const dayjs = require('dayjs');
const utc = require('dayjs/plugin/utc');
dayjs.extend(utc);
const dDate = dayjs('2020-06-19T03:55:12.000Z');
console.log(dDate.utcOffset(-7*60).format()); //2020-06-18T20:55:12-07:00
I used moment.js in the past. I tried Date-fnd for 24 hours. And finally, I moved to Day.js. It's new (start in late 2018) but it's growing so quick (take a look at this link and put the duration on 5 years). The great thing about it is that "IT ALWAYS DOES WHAT IT SAYS". Moment and Date-fns don't. (not always). It uses a wrapper and so you never work with the Date object directly. It solves difficulties and problems. It's immutable and always returns a new object and you can chain functions. Day.js has the smallest size (2kB).The documentation is awesome and you can up and running very fast. (It's more understandable that the way other libraries work.)
Here I have to say that Dayjs performance is not is good as Moment in calculations but is way better (than especially moment) in parsing and formating.
I strongly suggest you read this article: Why you shouldn't use Moment.js
Edit(1): As #GetSet mentioned in comments for OP that may need a solution in Moment.js I added it to the answer.
Edit(2): Adding the reason why you can't achieve your result the way OP solving it.
new Date() depends on local computer date setup - if any user has wrong date on his local computer - your system will take wrong dates from those users.
If you working with dates on background (storing in database or any other manipulations) - generate it on background (php, java etc.) and than send it to you html/javascript files.
you can use Date().toLocalString() method
// example:
var d = new Date().toLocalString("en-US", {
month: "long",
day: "2-digit",
year: "numeric",
});
for more information see:
https://www.w3schools.com/jsref/jsref_tolocalestring.asp
There are a couple of things it is vitally important to point out here.
There is no one US timezone, there are quite a few, for example America/Los_Angeles, America/Denver, America/Chicago, America/New_York, see the IANA Timezone list for all of them.
Please don't convert from one timezone to another using a fixed offset, this is really fragile. You wouldn't believe how many bugs I've seen in my career (from others, and yes, from myself!) due to this one mistake. Many timezones use Daylight Saving Time, so the UTC offset of the timezone varies by the date. For example, the Pacific Timezone currently varies between UTC-08:00 and UTC-07:00.
I would suggest using Moment Timezone to convert from one timezone to another.
For example:
const dateString = `2020-06-19T03:55:12.000Z`;
const timezones = ["America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles"];
console.log(`Time in UTC:`, moment(dateString).toISOString());
// Show the time in each timezone
timezones.forEach(timezone => {
let timeLocal = moment.tz(dateString, timezone);
console.log(`Time in ${timezone}:`, timeLocal.format('YYYY-MM-DD[T]HH:mm:ss.SSSZ'))
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://momentjs.com/downloads/moment-timezone-with-data.js">
</script>

Moment.js default year is 2001

Description of the Issue and Steps to Reproduce:
Receive user input as 3/3 var response
Parse into a date variable var date = moment(new Date(response))
Doing a console.log of date gives moment("2001-03-03T00:00:00.000")
The year defaults to 2001. Since the user may input the date in their own format, I didn't want to add in a format as I wouldn't know what format they might want to enter.
After looking around, I found some Moment github issues on this (#635, #912) which mentioned that the issue was resolved, but I am still getting the default year of 2001.
I also found a suggestion to set the year as this year if left unspecified:
if (date.year() === 2001) {
date.year() = moment().year();
}
This works, but feels like a dirty solution. Any ideas what I can do instead?
Thanks in advance!
Current Environment
Node.js v8.9.4
Moment.js v2.20.1
VS code v1.19.3
MS Bot SDK v3.14.0
p/s Still pretty new to the stackoverflow/ github issues, and not to sure where I should have posted instead. Please let me know if you need more information!
Use moment with a format string to ensure the format is proper. You might want to force the user to provide the year or use a date picker. The machine can only do so much
console.log(moment('3/3', 'MM/dd').toString());
// or
console.log(moment('3/3', 'dd/MM').toString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.js"></script>

ionic 2 ion-datetime ISO Format issue

I am using ion-datetime for my appointment form. While inserting it is working fine without any problem. But when I need to update the inserted appointment date form details from back end, the date value is not displaying in ion-datetime.
Below is my code:
update.html:
<ion-item class="border-bottom">
<ion-label class="ionselect" >Appointment Date:</ion-label>
<ion-datetime name="appdate" displayFormat="YYYY MMM DD" [(ngModel)]="leadDetailsUpdate.appt_date"></ion-datetime>
</ion-item>
update.ts:
leadDetailsUpdate={
appt_date:''
};
The Date format I am getting from back end as follows:
appt_date: "2017-01-01"
Below is the error message I am getting in console:
Error parsing date: "null". Please provide a valid ISO 8601 datetime format: https://www.w3.org/TR/NOTE-datetime
convert it to ISO format before displaying
var date = new Date('2017-01-01').toISOString()
console.log(date)
Even Gaurav is right, I found that if your timezone is not +0, you can have problems with that. I found somewhere this solution:
let tzoffset = (new Date()).getTimezoneOffset() * 60000; //offset in milliseconds
this.startTime = (new Date(this.myStartTime - tzoffset)).toISOString().slice(0,-1);
Then in my HTML I have it like this:
<ion-datetime displayFormat="HH:mm" [(ngModel)]="startTime" (ionChange)="changeCheckOutStartTime()" style="padding-left: 21px"></ion-datetime>
And in the changeCheckOutStartTime() method, I take the time and create a moment:
changeCheckOutStartTime() {
this.myStartTime = moment(this.startTime).toDate();
}
Using ISO format before displaying, like this:
this.myDate = new Date('2017-01-01').toISOString()
Will give us a difference of hours, each browser would do something different. In my case I had a difference of 5 hours (16/12/17 02:00 would be 16/12/17 07:00).
A better way would be to use moment as ionic recomends on its documentationn (https://ionicframework.com/docs/api/components/datetime/DateTime/#advanced-datetime-validation-and-manipulation)
Example:
Open console at root proyect and install moment: npm install moment --S.
Import moment in component file: import moment from 'moment';.
Set value of model variable: this.myDate = moment().format().
The best would be create a pipe. Well check this demo http://plnkr.co/edit/MHjUdC for inspiration, goog luck :)

Categories