toLocaleString() not converting time to correct string - node.js

So I have the below code, which does a bunch of conversions between dates/strings/moments, and it all seems to be converting properly until the line that calls .toLocaleString(), not sure why but it is converting 2022-05-04T17:00:00.000Z to 5/4/2022, 1:00:00 PM, although I believe it should be 5/4/2022, 5:00:00 PM.
let timezone = "Europe/Lisbon"
let currentDate = new Date() // initialize new date object
let localizedTime = moment.tz(currentDate, timezone) // convert it to a moment in the specified timezone
localizedTime.set({ h: 18, m: 0, s: 0 }) // set the hours to 18 (equivalent to 6PM or 18:00)
let postgresFormat = localizedTime.format() // format in a postgres identifiable way
console.log(localizedTime.format())
let convertedBack = moment.tz(postgresFormat, timezone) // convert from string stored in Postgres back to a moment object
console.log(convertedBack)
let localedProperly = convertedBack.toDate() // convert from a moment to a Date object
console.log(localedProperly)
let withLocale = localedProperly.toLocaleString("en-US", { timezone: timezone }) // try to format it in such a way that a client can read it in 'en-US' locale. The local will change dynamically based on the user's device.
console.log(withLocale)
Not sure how to fix this, any help is much appreciated :)

Related

Day.js unable to properly format date input in nodejs and reactjs

I am trying to implement dayjs package in my node.js application. I would like my date and time to be formatted like this:
2022-09-11T17:46:00+01:00
I have my codes like this:
const dayjs = require("dayjs");
const utc = require("dayjs/plugin/utc");
const customParseFormat = require('dayjs/plugin/customParseFormat');
const dayJsUTC = dayjs.extend(utc)
const dayJsDate = dayJsUTC.extend(customParseFormat)
I am trying to check that the format comes out this way 2022-09-11T17:46:00+01:00
Here is the code:
if(!dayJsDate( 2022-09-11T17:46:00+01:00, "YYYY-MM-DD HH:mm", true).isValid()){
return res.status(500).json('invalid date')
}
It is returning invalid date. I know I am not doing it properly. How can I do it properly to scale this validation?
Also, if I want to simply create only date, hour and minute without the additional time details, how can I do that using dayjs?
Sorry for not answering your question straight, but you could get what you want by defining your own function. When you pass no args to it, it returns just time in format like you wish, when passing a string to function - it return true or false, checking format. If you pass second param as "true", function will return date, hours and minutes.
const myDate = (input, noSecondsAndOffset) => {
const
offset = -(new Date().getTimezoneOffset()),
offsetHours = '0' + offset / 60,
offsetMins = '' + offset % 60,
timeZone = `${offsetHours}:${offsetMins}${offsetMins.length === 1 ? '0' : ''}`,
currTime = `${new Date().toJSON().slice(0, -5)}+${timeZone}`,
checker = (string) => !!string.match(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}:\d{2}/);
return typeof input === 'string'
? checker(string)
: !noSecondsAndOffset
? currTime
: currTime.slice(0, -9)
}

I am trying to get readable date from firestore

I am trying to get readable date from Timestamp data type in my firestore database.
for (var ticketDoc of ticketsSnapshot.docs) {
var timeStamp = await ticketDoc.data().TimePreferred;
console.log(timeStamp.toDate());
var time = new Date(timeStamp).toDate();
ticketDoc.data().TimePreferred = time;
tickets.push(ticketDoc.data());
}
I read the question about a similar problem at :
How do I convert a Firestore date/Timestamp to a JS Date()?
so, i tried to do same and i expect the output of readable date, although it gives me the correct result in
console.log(timeStamp.toDate());
but also it gives me an error. Console output as follow :-
2019-04-10T06:30:00.000Z
TypeError: (intermediate value).toDate is not a function
Not : I am trying to get readable date in postman
I don't know why this timestamp object doesn't have the .toDate() extension, but if it has the 'seconds' and 'nanoseconds' properties, you can turn it to a JS Data with
Date(data.seconds)
Change the following line:
var time = new Date(timeStamp).toDate();
into this:
var time = new Date(timeStamp).toDateString();
From the docs:
A string representing the date portion of the given Date object in human readable form in American English.
You can try in the following way
{{ formatDate(new Date(data.seconds*1000)) }}
You can use the format date function to display in desired format.
import moment from "moment";
format_date(value) {
if (value) {
return moment(String(value)).format("DD/MM/YYYY");
}
},
Have you tried changing this to
var time = (new Date(timeStamp)).toDateString();
If the TimePreferred field in your document is a Timestamp, you can get a valid Date object from it by simply calling toDate() on it.
So:
for (var ticketDoc of ticketsSnapshot.docs) {
var date = ticketDoc.data().TimePreferred.toDate();
}
None of these calls are asynchronous or returning a promise, so you don't need await.
From reasons that I don't know, it doesn't work at times, so a safer option would be to use the seconds and nanoseconds attributes found in the timestamp to convert it to date as follows:
const date = new Date(timestamp.seconds*1000 + timestamp.nanoseconds/100000)
// construct the date from the absolute time in milliseconds
Note:
1 second = 1000 ms
1 nanosecond = 10^-6 ms
You have to first make sure that the timestamp object is truly of type Timestamp.
to do this, after you get the Timestamp from Firebase, create the Timestamp object:
const timestampObject: Timestamp = !!timeStamp
? new Timestamp(timeStamp.seconds, timeStamp.nanoseconds)
: null;
For Angular
import { Location, DatePipe } from '#angular/common';
constructor(
public datepipe: DatePipe
) { }
const dayAsTimestamp = your_Timestamp_value;
const dayAsDate = new Date(dayAsTimestamp.seconds * 1000);
const dayAsString = this.datepipe.transform(dayAsDate, 'dd-MMM-yyyy');

Converting a UTC time via Timezones

I am displaying a date on the screen using the chrono crate.
The intention is to show the date in the users preferred time or UTC if no is set.
I have the UTC default set up, but I am unsure on the best method to record the user's timezone and how to apply that to the current date.
Note: date might not be set here so I'd prefer to modify date rather than use a different constructor.
let mut date: DateTime<UTC> = UTC::now();
//Convert to the User's Timezone if present
if let Some(user) = user {
//Extract the timezone
date.with_timezone(TimeZone::from_offset(&user.timezone));
}
let date_text = date.format("%H:%M %d/%m/%y").to_string();
What I would like is a type to use for user.timezone and an example on how to set the date.
You can use the chrono-tz crate, which allows you to convert a string to a timezone with chrono_tz::Tz::from_str("Europe/Berlin"). So all your user has to do is to supply a valid timezone string.
You can then use
fn date_time_str<Tz: chrono::TimeZone>(date: DateTime<Tz>, user: User) -> String {
if let Some(user) = user {
if let Ok(tz) = chrono_tz::Tz::from_str(user.timezone) {
let newdate = date.with_timezone(tz);
return newdate.format("%H:%M %d/%m/%y").to_string();
}
}
date.format("%H:%M %d/%m/%y").to_string()
}
You cannot modify the original date variable, because the types won't match. The timezone is part of the type. If you move completely to DateTime<chrono_tz::Tz>, then you could modify the variable, but all your uses of DateTime would need to be changed.

moment-timezone: unix timestamps with timezones

i am using momentjs.com with nodejs and im trying to get unix timestamps for multiple timezones, but sadly the the output is not correct.
code:
var moment = require('moment-timezone');
var berlin = moment.tz('Europe/Berlin').unix();
var angeles = moment.tz('America/Los_Angeles').unix();
var london = moment.tz('Europe/London').unix();
console.log(berlin);
console.log(angeles);
console.log(london);
output:
1472241731
1472241731
1472241731
A Unix Timestamp is always UTC based. It is the same timestamp everywhere on the planet simultaneously.
Changing the time zone of a moment object using moment-timezone only affects the local time value, such as used with the format function (and others). It does not change the moment in time being represented, and therefore does not change the underlying timestamp.
you can use Date.parse to get a timestamp, like this
const moment = require("moment-timezone")
const time = '2022-09-02 04:06:25'
var a = new Date(time).valueOf()
var b = Date.parse(moment.tz(time, "America/Chicago").format())
console.log(a) // China 1662062785000
console.log(b) // Chicago 1662109585000
To show correct time to user for different timezone, we can add timezone offset to unix UTC timestamp
const convertToNewTimeZone = (timeInMilliseconds: number, timezone: string) => {
const utcOffset = moment.tz(timeInMilliseconds, timezone).utcOffset();
return moment(timeInMilliseconds)
.add(utcOffset, 'minutes');
};
Note that if you are calculating time in browser, you may have to subtract the browser timezone offset
newTime.clone().subtract(moment().utcOffset(), 'minutes')

convert timestamp to pubnub timestamp of 17-digit precision unix time (UTC)

I am trying to convert timestamp 2016-02-11 03:31:18 to pubnub timestamp of 17-digit precision unix time (UTC) something like 13406746780720711 given in reference url given by pubnub
I have tried following but no luck
function parseDateTime(s) {
var b = s.split(/\D/);
return new Date(b[0],b[1]-1,b[2],b[3],b[4],b[5])
}
date = new Date(parseDateTime("2015-02-11 02:10:54") / 10000);
console.log(date.getTime());//142360085
Above example gives output 142360085 which is 10 characters where pubnub asks for 17 digit timestamp.
Reason behind doing this is i want to fetch unread messages of particular user and send an email at EOD via email.
After converting mytimestamp to 17-digit precision unix time (UTC) i will pass it to pubnub history function and get unread messages.
Convert Unix Timestamp to PubNub Timetoken 17-digit Precision
Easy as pie: timestamp * 10000
Except for PHP. ❌ PHP ❌ does not support this level of integer precision! You can instead use String Concatenation and Coercion.
$tt = $unixtime_milliseconds . "0000";
Your unix time must be represented in millisecond precision, no fractions / no floats.
Try out this example using JavaScript.
// Vars
var timestamp = +new Date;
var unix_time = document.getElementById("unix-timestamp");
var pubnub_time = document.getElementById("pubnub-timetoken");
// Conversion
function unix_to_pubnub(time) {
return time * 10000;
}
// Update Time
unix_time.innerHTML = timestamp;
pubnub_time.innerHTML = unix_to_pubnub(timestamp);
<span id="unix-timestamp"></span> - Unix Timestamp <br>
<span id="pubnub-timetoken"></span> - PubNub Timetoken
In Android get Current TimeToken
static Long getCurrentHourToken() {
return (Calendar.getInstance().getTimeInMillis()) * 10000L;
}
static Long getBeforeHourToken(int hours) {
return (Calendar.getInstance().getTimeInMillis() - TimeUnit.HOURS.toMillis(hours)) * 10000L;
}
In iOS how you can get current timestamp. This is written for PubNub.
static func currentTimeInMilliSeconds()-> CUnsignedLongLong {
let currentDate = Date()
let since1970 = currentDate.timeIntervalSince1970
return CUnsignedLongLong(since1970 * 1000)
}

Resources