React date format - RangeError: Invalid time value - javascript

I have a date in react app like
const messageDate = new Date(Date.parse(createdDate))
const options = { month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' } as const
const displayDate = new Intl.DateTimeFormat('en-GB', options).format(messageDate)
createdDate is from a GQL call
This seems to work and I have a formatted date.
I'm writing jest test with react-testing library
I'm not writing any test to test this function but the component it sits in, when I run the tests I can an error on format(messageDate)
RangeError: Invalid time value
Does the date function look ok, what could be causing this

fixed it with
const messageDate = new Date(createdDate)
const options = { month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' } as const
const displayDate = messageDate.toLocaleDateString('en-GB', options)

Related

How to POST javascript code in express instead of using script tag in html?

How can I make this work without using a script tag inside html. This is the current code, it works, but I want the code to come from express post request.
EDIT: If I run as script inside html, author, title, text, and date post correctly. If the code is inside express, everything posts except for date.
//html
<form action="/blogs" method="post">
<input type="hidden" id="date" name="date"/>
<script>
const event = new Date(Date.now());
const options = { year: 'numeric', month: 'long', day: 'numeric' };
const today = event.toLocaleDateString('en-US', options)
document.getElementById('date').value = today;
</script>
</form>
//express
app.post('/blogs', (req, res) => {
const { author, title, text, date } = req.body;
blogPosts.push({ author, title, text, date, })
res.send("New Post Added!")
})
This is what I tried...
//express
app.post('/blogs', (req, res) => {
const event = new Date(Date.now());
const options = { year: 'numeric', month: 'long', day: 'numeric' };
const today = event.toLocaleDateString('en-US', options)
const { author, title, text, date } = req.body;
blogPosts.push({ author, title, text, date, today })
res.send("New Post Added!")
})
Update: The final working code. Thanks Chris G!
app.post('/blogs', (req, res) => {
const event = new Date(Date.now());
const options = { year: 'numeric', month: 'long', day:
'numeric' };
const date = event.toLocaleDateString('en-US', options)
const { author, title, text } = req.body;
blogPosts.push({ author, title, text, date })
res.send("New Post Added!")
})
I know there are a lot of pros that will look at this and say "idiot", which is fair but please understand that I'm just starting out in programming and I really love doing this! I look up to all the experts on here and envy your talent. I want to learn, not asking for a freebie or someone to do my work. Just an explanation or someone to point me in the right direction would be more than enough. Thank you for your time!

Firebase firestore timestamp query returns no documents

I'm trying to retrieve some documents from a collection based on the timestamp falling on a specific day. I know I have documents in my collection that fall between these time stamps but it keeps returning nothing. If I remove the 'startTime' query parameters then I am able to retrieve documents.
Am I querying the timestamps incorrectly?
StartTime stored as timestamp in firestore
// Get bookings from firestore
firestore
.collection('bookings')
.where('studio.ID', '==', 'kM8p1jSenI4M0Mr1PzBo') /// Works fine with this query
.where('startTime', '>=', dayjs(date).valueOf()) /// 1631415616880
.where('startTime', '<', dayjs(date).add(1, 'day').valueOf()) /// 1631502016880
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
console.table(doc.data());
setBookings(doc.data());
});
Also tried query as a date object:
const [date, setDate] = useState(new Date(new Date().setHours(0, 0, 0, 0))); //setting initial state to current day midnight
const [step, setStep] = useState(0); // Count the days ahead the user is trying to book.
const [alert, setAlert] = useState(false); // Alert when trying to exceed booking window.
const [bookings, setBookings] = useState({});
const bookingWindowAllowed = 7; // Used to limit the forward bookings (evaluated vs state.step)
useEffect(() => {
setLoading(true);
console.log('Set date is:', date);
const setDate = new Date(dayjs(date).valueOf()); //Date object for today
const futureDate = new Date(dayjs(date).add(1, 'day').valueOf()); //Date object for tomorrow
console.log('Set date is:', setDate);
console.log('Future date is:', futureDate);
// Get bookings from firestore
firestore
.collection('bookings')
.where('studio.ID', '==', 'kM8p1jSenI4M0Mr1PzBo') /// Works fine with this query
.where('startTime', '>=', setDate) /// 1631415616880
.where('startTime', '<', futureDate) /// 1631502016880
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
console.table(doc.data());
setBookings(doc.data());
});
setLoading(false);
})
.catch((error) => {
console.log('Error getting documents: ', error);
setLoading(false);
});
}, [date]);
Try using Firestore Timestamp object instead of using timestamp in where() since you are storing it as Timestamp. Also the value is stored in field startTime so you don't need .seconds in where():
firestore
.collection('bookings')
.where('studio.ID', '==', 'kM8p1jSenI4M0Mr1PzBo')
.where('startTime', '>=', firebase.firestore.Timestamp.fromMillis(dayjs(date).valueOf()))
.where('startTime', '<', firebase.firestore.Timestamp.fromMillis(dayjs(date).add(1, 'day').valueOf()))
.get()
If you need to use the Unix timestamp in query then you would have to store it as number in Firestore.

dialogflow how to play the next time available from google calendar

how are you? English are my native language, so I apologize right away.
what I have is a bot in the dialogflow, which with some interactions marks events on the agenda.
an example:
Bot: hello welcome to the hairdresser, would you like to make an appointment?
User: Yes
Bot: What's your name?
User: Welyson
Bot: What day would you like?
User: tomorrow
Bot: What time?
User: 3pm
If you have space on the google calendar
Bot: Okay, you were scheduled for February 21st at 3pm
-If you don't have space on the google calendar
Bot: Oops, it appears that we have no vacancies for that day or time, type check to try another time.
Where I got the code as an example
The code below does this:
'use strict';
const functions = require('firebase-functions');
const {google} = require('googleapis');
const {WebhookClient} = require('dialogflow-fulfillment');
// Enter your calendar ID below and service account JSON below
const calendarId = "id google agenda ";
const serviceAccount = {json file}; // Starts with {"type": "service_account",...
// Set up Google Calendar Service account credentials
const serviceAccountAuth = new google.auth.JWT({
email: serviceAccount.client_email,
key: serviceAccount.private_key,
scopes: 'https://www.googleapis.com/auth/calendar'
});
const calendar = google.calendar('v3');
process.env.DEBUG = 'dialogflow:*'; // enables lib debugging statements
const timeZoneOffset = '-03:00';
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
const appointment_nome = agent.parameters.nome;
function makeAppointment (agent) {
const dateTimeStart = new Date(Date.parse(agent.parameters.date.split('T')[0] + 'T' + agent.parameters.time.split('T')[1].split('-')[0] + timeZoneOffset));
const dateTimeEnd = new Date(new Date(dateTimeStart).setHours(dateTimeStart.getHours() + 1));
const agendamentoString = FormtData(new Date(agent.parameters.date.split('T')[0])) + " às " + agent.parameters.time.split('T')[1].split('-')[0];
// Check the availibility of the time, and make an appointment if there is time on the calendar
return createCalendarEvent(dateTimeStart, dateTimeEnd, appointment_nome).then(() => {
let mensagem = `Okay, you were scheduled for *${agendamentoString}* ✅.`;
response.json({"fulfillmentText": mensagem});
}).catch(() => {
let mensagem = `Oops, it appears that we have no vacancies for that day or time, type **check** to try another time.`;
response.json({"fulfillmentText": mensagem});
});
}
let intentMap = new Map();
//intentMap.set('Schedule Appointment', makeAppointment);
intentMap.set('Default Welcome Intent - yes', makeAppointment);
agent.handleRequest(intentMap);
});
function createCalendarEvent (dateTimeStart, dateTimeEnd, appointment_nome) {
return new Promise((resolve, reject) => {
calendar.events.list({
auth: serviceAccountAuth, // List events for time period
calendarId: calendarId,
timeMin: dateTimeStart.toISOString(),
timeMax: dateTimeEnd.toISOString()
}, (err, calendarResponse) => {
// Check if there is a event already on the Calendar
if (err || calendarResponse.data.items.length > 0) {
reject(err || new Error('Requested time conflicts with another appointment'));
} else {
// Create event for the requested time period
calendar.events.insert({ auth: serviceAccountAuth,
calendarId: calendarId,
resource: {summary:"Cliente: " + appointment_nome, description: "Cliente: " + appointment_nome,
start: {dateTime: dateTimeStart},
end: {dateTime: dateTimeEnd}}
}, (err, event) => {
err ? reject(err) : resolve(event);
}
);
}
});
});
}
function FormtData(date){
var nomesMes = [
"Janeiro", "Fevereiro", "Março",
"Abril", "Maio", "Junho","Julho",
"Agosto", "Setembro", "Outubro",
"Novembro", "Dezembro"
];
var dia = date.getDate();
var mesIndex = date.getMonth();
var ano = date.getFullYear();
return dia + ' ' + nomesMes[mesIndex];
}
But the problem is that if my schedule has too many times scheduled, the schedule will become tiring for the user!
I thought of something, like
Bot: Would you like to schedule a haircut?
User: yes
Bot: How about February 21st at 1 pm?
-If the user agrees the time is marked in the agenda:
User: Yes
Bot: Okay, you were scheduled for February 21st at 1pm
-If the user disagrees he goes to the next available time:
User: No
Bot: How about February 21st at 2 pm?
I tried something with the CalDAV API to read the google calendar, I didn't get any progress
Does anyone have any idea how I would do this? Thank you very much in advance

Timezone issue in javascript Date object

I am working on an employee time tracking application with its backend on node.js. The problem is when the site is hosted locally it registers the time in gmt +05:30 which is correct as i live in india but when i hosted the site on heroku server (which i think the heroku's server time zone is set to 00:00) and accesses it from same computer. then, it registers the time in gmt +00:00.
Now what i want is that when its hosted on heroku server it should know the time zone of the user (Example if user resides in Los Angeles and creates an entry. then, it should register the entry in GMT-7 timezone)
Screenshot
Code
const postSchema = {
username: String,
entry: String,
rawEntry: Number,
exit: String,
rawExit: Number,
duration: String,
complete: Boolean,
createdAt: {
type: Date,
default: Date.now()
}
};
logEntry Route
app.get('/logEntry', function(req, res) {
if (req.isAuthenticated()) {
const t = new Date();
const now = date.format(t, 'DD/MMM/YYYY ddd hh:mm:ss A Z');
const rawNow = Date.now();
const post = new Post({
username: nameUser,
entry: now,
rawEntry: rawNow,
complete: false
});
post.save(function(err) {
if (err) {
console.log(err);
}
res.redirect('/logged');
});
} else {
res.redirect('/');
}
});
This is a very common problem that we face with timezone.
Client side get getTimezoneOffset and add or remove seconds that are over.
const d = new Date();
const n = d.getTimezoneOffset();
console.log("your PC or laptop timezone more or less in seconds", n); // -330
So, when you will run this code in local that time as you told you are having gmt +05:30 getTimezoneOffset will output -330 sec means 5 hour and 30 mins.
So you can remove these seconds from the current time and set accordingly.
or
You can use in build javascript function
const d1 = new Date();
console.log(d1); //Thu Aug 29 2019 17:56:14 GMT+0530
d1.toUTCString(); // Thu, 29 Aug 2019 12:26:39 GMT
Check the differance is +5:30 hours.
I solved this problem by executing new Date() on the client side and then passing in url to the server for further action.
Client side code =>
<button onclick="createLogin()" class="btn btn-outline-primary btn-lg btn-block entryBtn">
CREATE LOGIN ENTRY
</button>
<script>
function createLogin() {
let t = new Date();
console.log(t);
let url = '/logEntry/' + t;
window.location = url;
}
</script>
Server side code =>
app.get('/logEntry/:date', function(req, res) {
if (req.isAuthenticated()) {
const now = req.params.date;
const nowDayTime = now.substring(0, 25);
const timeZone = now.substring(25, now.length);
const rawNow = Date.now();
const post = new Post({
username: nameUser,
entryDayTime: nowDayTime,
entryTimeZone: timeZone,
rawEntry: rawNow,
complete: false
});
post.save(function(err) {
if (err) {
console.log(err);
}
res.redirect('/logged');
});
} else {
res.redirect('/');
}
});

Get all docs by a given date ? (createdAt)

I have this date given by a date picker widget:
let targetDate = '2019-01-12';
All my documents have a createtAt date generated by timestamps:
"createdAt": "2019-01-12T21:49:05.546Z"
I want to get all documents that field createdAt matches with my given date.
I tried using $elemMatch:
const allDailies = await Daily.find({ createdAt: { $elemMatch: dateTarget } });
const allDailies = await Daily.find({ createdAt: { $elemMatch: { from: dateTarget, to: dateTarget} } });
And no one works, how can I do this query? Actually I can't modify my Schema :(
EDIT:
router.get('/daily/:date', async (req, res) => {
try {
const targetDate = new RegExp(`^${req.params.date}`);
const allDailies = await Daily.find({ createdAt: { $regex: targetDate } });
console.log('Dailies', allDailies);
return res.json({ allDailies });
} catch (error) {
return res.sendStatus(httpStatus.INTERNAL_SERVER_ERROR);
}
});
It returns a 500 error
Convert your targetDate to the same type as createdAt and use it on query as tatgetDate. Not dateTarget as you use it now (you typed it wrong).
You have to convert your target date in to ISODate format. But this will be taken care by mongoose by default so.. What you want to do is change your query like this
Model.find({createdAt:{$gte:params.frm, $lte:params.to}},callback);
or if you want to just give a single date try like this
Model.find({createdAt:dateTarget},callback);

Categories

Resources