fix dates ant TZ, cleanup
This commit is contained in:
@ -11,6 +11,7 @@ import { ToastContainer } from 'react-toastify';
|
||||
const common = require('src/helpers/common');
|
||||
//todo import Availability type from prisma schema
|
||||
import { isBefore, addMinutes, isAfter, isEqual, set, getHours, getMinutes, getSeconds } from 'date-fns'; //ToDo obsolete
|
||||
import { stat } from 'fs';
|
||||
|
||||
const { DateTime, FixedOffsetZone } = require('luxon');
|
||||
|
||||
@ -21,7 +22,7 @@ const fetchConfig = async () => {
|
||||
return config.default;
|
||||
};
|
||||
|
||||
export default function AvailabilityForm({ publisherId, existingItems, inline, onDone, date, datePicker = false }) {
|
||||
export default function AvailabilityForm({ publisherId, existingItems, inline, onDone, date, cartEvent, datePicker = false }) {
|
||||
|
||||
const router = useRouter();
|
||||
const urls = {
|
||||
@ -67,14 +68,13 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
||||
}, []);
|
||||
|
||||
|
||||
// Define the minimum and maximum times
|
||||
const minTime = new Date();
|
||||
minTime.setHours(9, 0, 0, 0); // 8:00 AM
|
||||
const maxTime = new Date();
|
||||
maxTime.setHours(19, 30, 0, 0); // 8:00 PM
|
||||
// get cart event or set default time for Sofia timezone
|
||||
const minTime = cartEvent?.startTime || DateTime.now().set({ hour: 8, minute: 0, second: 0, millisecond: 0, zone: 'Europe/Sofia' }).toJSDate();
|
||||
const maxTime = cartEvent?.endTime || DateTime.now().set({ hour: 20, minute: 0, second: 0, millisecond: 0, zone: 'Europe/Sofia' }).toJSDate();
|
||||
|
||||
useEffect(() => {
|
||||
setTimeSlots(generateTimeSlots(minTime, maxTime, 90, availabilities));
|
||||
setTimeSlots(generateTimeSlots(new Date(minTime), new Date(maxTime), cartEvent.shiftDuration, availabilities));
|
||||
console.log("AvailabilityForm: minTime: " + common.getTimeFormatted(minTime) + ", maxTime: " + common.getTimeFormatted(maxTime), ", " + cartEvent.shiftDuration + " min. shifts");
|
||||
}, []);
|
||||
|
||||
|
||||
@ -189,34 +189,11 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
||||
|
||||
// Common function to set shared properties
|
||||
function setSharedAvailabilityProperties(availability, group, timeSlots) {
|
||||
// Define a fixed offset for Sofia (+2 hours from UTC, ignoring DST)
|
||||
const fixedZone = FixedOffsetZone.instance(120); // Offset in minutes
|
||||
|
||||
// availability.startTime = group[0].startTime;
|
||||
// availability.endTime = group[group.length - 1].endTime;
|
||||
// Adjust start time
|
||||
let startTime = DateTime.fromJSDate(group[0].startTime, { zone: 'utc' })
|
||||
.setZone(fixedZone, { keepLocalTime: true });
|
||||
startTime = startTime.set({
|
||||
hour: group[0].startTime.getUTCHours(),
|
||||
minute: group[0].startTime.getUTCMinutes(),
|
||||
second: group[0].startTime.getUTCSeconds()
|
||||
});
|
||||
|
||||
// Adjust end time
|
||||
let endTime = DateTime.fromJSDate(group[group.length - 1].endTime, { zone: 'utc' })
|
||||
.setZone(fixedZone, { keepLocalTime: true });
|
||||
endTime = endTime.set({
|
||||
hour: group[group.length - 1].endTime.getUTCHours(),
|
||||
minute: group[group.length - 1].endTime.getUTCMinutes(),
|
||||
second: group[group.length - 1].endTime.getUTCSeconds()
|
||||
});
|
||||
|
||||
// Update the availability object with the new times
|
||||
availability.startTime = startTime.toJSDate();
|
||||
availability.endTime = endTime.toJSDate();
|
||||
|
||||
availability.name = common.getTimeFomatted(group[0].startTime) + "-" + common.getTimeFomatted(group[group.length - 1].endTime);
|
||||
let startTime = common.setTimeHHmm(new Date(availability.startTime || day), common.getTimeFormatted(group[0].startTime));
|
||||
let endTime = common.setTimeHHmm(new Date(availability.endTime || day), common.getTimeFormatted(group[group.length - 1].endTime));
|
||||
availability.startTime = startTime;
|
||||
availability.endTime = endTime;
|
||||
availability.name = common.getTimeFormatted(group[0].startTime) + "--" + common.getTimeFormatted(group[group.length - 1].endTime);
|
||||
|
||||
availability.isWithTransportIn = group[0].isFirst && timeSlots[0].isWithTransport;
|
||||
availability.isWithTransportOut = group[group.length - 1].isLast && timeSlots[timeSlots.length - 1].isWithTransport;
|
||||
@ -308,27 +285,19 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
||||
let currentTime = start;
|
||||
|
||||
//const baseDate = new Date(Date.UTC(2000, 0, 1, 0, 0, 0));
|
||||
const baseDate = new Date(start);
|
||||
//const baseDate = new Date(start);
|
||||
|
||||
while (isBefore(currentTime, end)) {
|
||||
let slotStart = normalizeTime(currentTime, baseDate);
|
||||
let slotEnd = normalizeTime(addMinutes(currentTime, increment), baseDate);
|
||||
let slotStart = currentTime;
|
||||
let slotEnd = addMinutes(currentTime, increment);
|
||||
|
||||
const isChecked = items.some(item => {
|
||||
let itemStart = item.startTime ? normalizeTime(new Date(item.startTime), baseDate) : null;
|
||||
let itemEnd = item.endTime ? normalizeTime(new Date(item.endTime), baseDate) : null;
|
||||
|
||||
return itemStart && itemEnd &&
|
||||
(slotStart.getTime() < itemEnd.getTime()) &&
|
||||
(slotEnd.getTime() > itemStart.getTime());
|
||||
});
|
||||
|
||||
slots.push({
|
||||
startTime: slotStart,
|
||||
endTime: slotEnd,
|
||||
isChecked: isChecked,
|
||||
return item.startTime && item.endTime &&
|
||||
(slotStart.getTime() < item.endTime.getTime()) &&
|
||||
(slotEnd.getTime() > item.startTime.getTime());
|
||||
});
|
||||
|
||||
slots.push({ startTime: slotStart, endTime: slotEnd, isChecked: isChecked, });
|
||||
currentTime = addMinutes(currentTime, increment);
|
||||
}
|
||||
|
||||
@ -342,16 +311,6 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
||||
return slots;
|
||||
};
|
||||
|
||||
// Normalize the time part of a date by using a base date
|
||||
function normalizeTime(date, baseDate) {
|
||||
return set(baseDate, {
|
||||
hours: getHours(date),
|
||||
minutes: getMinutes(date),
|
||||
seconds: getSeconds(date),
|
||||
milliseconds: 0
|
||||
});
|
||||
}
|
||||
|
||||
const TimeSlotCheckboxes = ({ slots, setSlots, items: [] }) => {
|
||||
const [allDay, setAllDay] = useState(slots.every(slot => slot.isChecked));
|
||||
const handleAllDayChange = (e) => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, use } from 'react';
|
||||
import { Calendar, momentLocalizer, dateFnsLocalizer } from 'react-big-calendar';
|
||||
import 'react-big-calendar/lib/css/react-big-calendar.css';
|
||||
import AvailabilityForm from '../availability/AvailabilityForm';
|
||||
@ -18,11 +18,13 @@ import { MdToday } from 'react-icons/md';
|
||||
|
||||
import { useSwipeable } from 'react-swipeable';
|
||||
import axiosInstance from '../../src/axiosSecure';
|
||||
import { set } from 'date-fns';
|
||||
import { get } from 'http';
|
||||
|
||||
// import { set, format, addDays } from 'date-fns';
|
||||
// import { isEqual, isSameDay, getHours, getMinutes } from 'date-fns';
|
||||
import { filter } from 'jszip';
|
||||
import e from 'express';
|
||||
// import { filter } from 'jszip';
|
||||
// import e from 'express';
|
||||
|
||||
|
||||
|
||||
@ -46,7 +48,7 @@ const messages = {
|
||||
// Any other labels you want to translate...
|
||||
};
|
||||
|
||||
const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
||||
const AvCalendar = ({ publisherId, events, selectedDate, cartEvents }) => {
|
||||
|
||||
const isAdmin = ProtectedRoute.IsInRole(UserRole.ADMIN);
|
||||
|
||||
@ -65,7 +67,15 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
||||
return { start, end };
|
||||
});
|
||||
|
||||
const [cartEvent, setCartEvent] = useState(null);
|
||||
function getCartEvent(date) {
|
||||
const dayOfWeek = common.getDayOfWeekNameEnEnumForDate(date);
|
||||
const ce = cartEvents?.find(e => e.dayofweek === dayOfWeek);
|
||||
return ce;
|
||||
}
|
||||
|
||||
useEffect(() => { setCartEvent(getCartEvent(date)); },
|
||||
[date, selectedEvents]);
|
||||
|
||||
// Update internal state when `events` prop changes
|
||||
useEffect(() => {
|
||||
@ -113,6 +123,7 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
||||
//setDisplayedEvents(evts);
|
||||
}, [visibleRange, evts, currentView]);
|
||||
|
||||
// todo: review that
|
||||
const handlers = useSwipeable({
|
||||
onSwipedLeft: () => navigate('NEXT'),
|
||||
onSwipedRight: () => navigate('PREV'),
|
||||
@ -201,18 +212,13 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
||||
return existingEvents;
|
||||
};
|
||||
|
||||
// Define min and max times
|
||||
const minHour = 8; // 8:00 AM
|
||||
const maxHour = 20; // 8:00 PM
|
||||
const minTime = new Date();
|
||||
minTime.setHours(minHour, 0, 0);
|
||||
const maxTime = new Date();
|
||||
maxTime.setHours(maxHour, 0, 0);
|
||||
const totalHours = maxHour - minHour;
|
||||
|
||||
// const totalHours = maxHour - minHour;
|
||||
|
||||
const handleSelect = ({ mode, start, end }) => {
|
||||
const startdate = typeof start === 'string' ? new Date(start) : start;
|
||||
const enddate = typeof end === 'string' ? new Date(end) : end;
|
||||
//we set the time to proper timezone
|
||||
const startdate = common.setTimezone(start);
|
||||
const enddate = common.setTimezone(end);
|
||||
|
||||
if (!start || !end) return;
|
||||
//readonly for past dates (ToDo: if not admin)
|
||||
@ -224,27 +230,10 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
||||
end = common.setTimeHHmm(startdate, "23:59");
|
||||
}
|
||||
|
||||
const startMinutes = common.getTimeInMinutes(start);
|
||||
const endMinutes = common.getTimeInMinutes(end);
|
||||
|
||||
// Adjust start and end times to be within min and max hours
|
||||
if (startMinutes < common.getTimeInMinutes(common.setTimeHHmm(start, minHour))) {
|
||||
start = common.setTimeHHmm(start, minHour);
|
||||
}
|
||||
if (endMinutes > common.getTimeInMinutes(common.setTimeHHmm(end, maxHour))) {
|
||||
end = common.setTimeHHmm(end, maxHour);
|
||||
}
|
||||
|
||||
setDate(start);
|
||||
|
||||
// get exising events for the selected date
|
||||
//ToDo: properly fix this. filterEvents does not return the expcted results
|
||||
let existingEvents = filterEvents(evts, publisherId, startdate);
|
||||
// if existingEvents is empty - create new with the selected range
|
||||
// if (existingEvents.length === 0) {
|
||||
// existingEvents = [{ startTime: start, endTime: end }];
|
||||
// }
|
||||
console.log("handleSelect: " + existingEvents);
|
||||
setCartEvent(getCartEvent(date));
|
||||
setSelectedEvents(existingEvents);
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
@ -509,8 +498,8 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
||||
onSelectSlot={handleSelect}
|
||||
onSelectEvent={handleEventClick}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
min={minTime} // Set minimum time
|
||||
max={maxTime} // Set maximum time
|
||||
min={cartEvent?.startTime} // Set minimum time
|
||||
max={cartEvent?.endTime} // Set maximum time
|
||||
messages={messages}
|
||||
view={currentView}
|
||||
views={['month', 'week', 'agenda']}
|
||||
@ -541,6 +530,7 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
||||
date={date}
|
||||
onDone={handleDialogClose}
|
||||
inline={true}
|
||||
cartEvent={cartEvent}
|
||||
// Pass other props as needed
|
||||
/>
|
||||
</div>
|
||||
|
@ -69,8 +69,8 @@ export default function CartEventForm(props: IProps) {
|
||||
try {
|
||||
console.log("fetching cart event from component " + router.query.id);
|
||||
const { data } = await axiosInstance.get(urls.apiUrl + id);
|
||||
data.startTime = common.formatTimeHHmm(data.startTime)
|
||||
data.endTime = common.formatTimeHHmm(data.endTime)
|
||||
data.startTime = common.getTimeFormatted(data.startTime)
|
||||
data.endTime = common.getTimeFormatted(data.endTime)
|
||||
setEvt(data);
|
||||
|
||||
console.log("id:" + evt.id);
|
||||
|
@ -11,9 +11,15 @@ function PublisherSearchBox({ id, selectedId, onChange, isFocused, filterDate, s
|
||||
const [searchResults, setSearchResults] = useState([]);
|
||||
const [selectedDate, setSelectedDate] = useState(filterDate);
|
||||
|
||||
|
||||
// useEffect(() => {
|
||||
// fetchPublishers();
|
||||
// }, []); // Empty dependency array ensures this useEffect runs only once
|
||||
|
||||
// Update publishers when filterDate or showList changes
|
||||
useEffect(() => {
|
||||
fetchPublishers();
|
||||
}, []); // Empty dependency array ensures this useEffect runs only once
|
||||
}, [filterDate, showList]);
|
||||
|
||||
const fetchPublishers = async () => {
|
||||
console.log("fetchPublishers called");
|
||||
@ -60,10 +66,7 @@ function PublisherSearchBox({ id, selectedId, onChange, isFocused, filterDate, s
|
||||
// console.log("filterDate changed = ", filterDate);
|
||||
// }, [filterDate]);
|
||||
|
||||
// Update publishers when filterDate or showList changes
|
||||
useEffect(() => {
|
||||
fetchPublishers();
|
||||
}, [filterDate, showList]);
|
||||
|
||||
|
||||
// Update selectedItem when selectedId changes and also at the initial load
|
||||
useEffect(() => {
|
||||
|
@ -161,7 +161,7 @@ export default async function handler(req, res) {
|
||||
newPubs: newPubs,
|
||||
placeName: assignment.shift.cartEvent.location.name,
|
||||
dateStr: common.getDateFormated(assignment.shift.startTime),
|
||||
time: common.formatTimeHHmm(assignment.shift.startTime),
|
||||
time: common.getTimeFormatted(assignment.shift.startTime),
|
||||
sentDate: common.getDateFormated(new Date())
|
||||
};
|
||||
|
||||
@ -383,7 +383,7 @@ export default async function handler(req, res) {
|
||||
email: pubsToSend[i].email,
|
||||
placeName: assignment.shift.cartEvent.location.name,
|
||||
dateStr: common.getDateFormated(assignment.shift.startTime),
|
||||
time: common.formatTimeHHmm(assignment.shift.startTime),
|
||||
time: common.getTimeFormatted(assignment.shift.startTime),
|
||||
sentDate: common.getDateFormated(new Date())
|
||||
};
|
||||
let results = emailHelper.SendEmailHandlebars(
|
||||
|
@ -15,13 +15,14 @@ import { getServerSession } from "next-auth/next"
|
||||
|
||||
import PublisherSearchBox from '../components/publisher/PublisherSearchBox';
|
||||
import PublisherInlineForm from '../components/publisher/PublisherInlineForm';
|
||||
import CartEventForm from "components/cartevent/CartEventForm";
|
||||
|
||||
|
||||
interface IProps {
|
||||
initialItems: Availability[];
|
||||
initialUserId: string;
|
||||
}
|
||||
export default function IndexPage({ initialItems, initialUserId }: IProps) {
|
||||
export default function IndexPage({ initialItems, initialUserId, cartEvents }: IProps) {
|
||||
const { data: session } = useSession();
|
||||
const [userName, setUserName] = useState(session?.user?.name);
|
||||
const [userId, setUserId] = useState(initialUserId);
|
||||
@ -78,7 +79,7 @@ export default function IndexPage({ initialItems, initialUserId }: IProps) {
|
||||
<div className="text-center font-bold pb-3 xs:pb-1">
|
||||
<PublisherInlineForm publisherId={userId} />
|
||||
</div>
|
||||
<AvCalendar publisherId={userId} events={events} selectedDate={new Date()} />
|
||||
<AvCalendar publisherId={userId} events={events} selectedDate={new Date()} cartEvents={cartEvents} />
|
||||
</div>
|
||||
</div>
|
||||
</ProtectedRoute>
|
||||
@ -223,10 +224,30 @@ export const getServerSideProps = async (context) => {
|
||||
return updatedItem;
|
||||
});
|
||||
|
||||
// log first availability startTime to verify timezone and UTC conversion
|
||||
|
||||
console.log("First availability startTime: " + items[0].startTime);
|
||||
console.log("First availability startTime: " + items[0].startTime.toLocaleString());
|
||||
|
||||
const prisma = common.getPrismaClient();
|
||||
let cartEvents = await prisma.cartEvent.findMany({
|
||||
where: {
|
||||
isActive: true,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
startTime: true,
|
||||
endTime: true,
|
||||
dayofweek: true,
|
||||
shiftDuration: true,
|
||||
}
|
||||
});
|
||||
cartEvents = common.convertDatesToISOStrings(cartEvents);
|
||||
return {
|
||||
props: {
|
||||
initialItems: items,
|
||||
userId: session?.user.id,
|
||||
cartEvents: cartEvents,
|
||||
// messages: (await import(`../content/i18n/${context.locale}.json`)).default
|
||||
},
|
||||
};
|
||||
|
@ -339,14 +339,8 @@ exports.compareTimes = function (time1, time2) {
|
||||
const time2String = `${getHours(time2)}:${getMinutes(time2)}`;
|
||||
return time1String.localeCompare(time2String);
|
||||
};
|
||||
|
||||
exports.normalizeTime = function (date, baseDate) {
|
||||
// return set(baseDate, {
|
||||
// hours: getHours(date),
|
||||
// minutes: getMinutes(date),
|
||||
// seconds: getSeconds(date),
|
||||
// milliseconds: 0
|
||||
// });
|
||||
//don't use date-fns
|
||||
let newDate = new Date(baseDate);
|
||||
newDate.setHours(date.getHours(), date.getMinutes(), date.getSeconds(), 0);
|
||||
return newDate;
|
||||
@ -549,54 +543,96 @@ exports.getCurrentYearMonth = () => {
|
||||
const month = String(currentDate.getMonth() + 1).padStart(2, '0'); // Month is 0-indexed
|
||||
return `${year}-${month}`;
|
||||
}
|
||||
exports.getTimeFormatted = function (date) {
|
||||
const dateTime = DateTime.fromJSDate(date, { zone: 'Europe/Sofia' });
|
||||
return dateTime.toFormat('HH:mm');
|
||||
|
||||
|
||||
// new date FNs
|
||||
// Utility to handle date parsing consistently
|
||||
const parseDate = (input) => {
|
||||
return (typeof input === 'string' || input instanceof Date)
|
||||
? DateTime.fromJSDate(new Date(input), { zone: 'Europe/Sofia' })
|
||||
: DateTime.now({ zone: 'Europe/Sofia' });
|
||||
};
|
||||
exports.parseDate = parseDate;
|
||||
|
||||
// Set timezone to 'Europe/Sofia' without translating time
|
||||
exports.setTimezone = (input) => {
|
||||
let dateTime = parseDate(input);
|
||||
dateTime = dateTime.setZone('Europe/Sofia', { keepLocalTime: true });
|
||||
return dateTime.toJSDate();
|
||||
};
|
||||
|
||||
// format date to 'HH:mm' time string required by the time picker
|
||||
exports.formatTimeHHmm = function (input) {
|
||||
// Check if the input is a string or a Date object
|
||||
const date = (typeof input === 'string') ? new Date(input) : input;
|
||||
// Format date to a specified format, defaulting to 'HH:mm'
|
||||
exports.getTimeFormatted = (input, format = 'HH:mm') => {
|
||||
const dateTime = parseDate(input);
|
||||
return dateTime.toFormat(format);
|
||||
};
|
||||
|
||||
return date.toLocaleTimeString('en-US', {
|
||||
hour12: false,
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
timeZone: 'Europe/Sofia'
|
||||
}).substring(0, 5);
|
||||
}
|
||||
// Set time in 'HH:mm' format to a date and return as JS Date in Sofia timezone
|
||||
exports.setTimeHHmm = (input, timeString) => {
|
||||
let dateTime = parseDate(input);
|
||||
const [hour, minute] = timeString.split(':').map(Number);
|
||||
dateTime = dateTime.set({ hour, minute, second: 0, millisecond: 0 });
|
||||
return dateTime.toJSDate();
|
||||
};
|
||||
|
||||
|
||||
//parse 'HH:mm' time string to date object
|
||||
// Parse 'HH:mm' time string to a JS Date object in Sofia timezone for today
|
||||
exports.parseTimeHHmm = (timeString) => {
|
||||
// If timeString is already a date, return it as is
|
||||
if (timeString instanceof Date) {
|
||||
return timeString;
|
||||
}
|
||||
|
||||
const [hours, minutes] = timeString.split(':');
|
||||
const date = new Date();
|
||||
date.setHours(hours);
|
||||
date.setMinutes(minutes);
|
||||
return date;
|
||||
}
|
||||
|
||||
exports.setTimeHHmm = (date, timeStringOrHours) => {
|
||||
const newDate = new Date(date);
|
||||
|
||||
if (typeof timeStringOrHours === 'string' && timeStringOrHours.includes(':')) {
|
||||
// If hours is a string in "HH:mm" format
|
||||
const [h, m] = timeStringOrHours.split(':');
|
||||
newDate.setHours(parseInt(h, 10), parseInt(m, 10), 0, 0);
|
||||
} else {
|
||||
// If hours and minutes are provided separately
|
||||
newDate.setHours(parseInt(timeStringOrHours, 10), 0, 0, 0);
|
||||
}
|
||||
|
||||
return newDate;
|
||||
const dateTime = DateTime.now({ zone: 'Europe/Sofia' });
|
||||
const [hour, minute] = timeString.split(':').map(Number);
|
||||
return dateTime.set({ hour, minute, second: 0, millisecond: 0 }).toJSDate();
|
||||
};
|
||||
|
||||
// ToDo: update all uses of this function to use the new one
|
||||
|
||||
// exports.getTimeFormatted = function (date) {
|
||||
// const dateTime = DateTime.fromJSDate(date, { zone: 'Europe/Sofia' });
|
||||
// return dateTime.toFormat('HH:mm');
|
||||
// };
|
||||
|
||||
// exports.setTimeHHmm = (date, timeStringOrHours) => {
|
||||
// const newDate = new Date(date);
|
||||
|
||||
// if (typeof timeStringOrHours === 'string' && timeStringOrHours.includes(':')) {
|
||||
// // If hours is a string in "HH:mm" format
|
||||
// const [h, m] = timeStringOrHours.split(':');
|
||||
// newDate.setHours(parseInt(h, 10), parseInt(m, 10), 0, 0);
|
||||
// } else {
|
||||
// // If hours and minutes are provided separately
|
||||
// newDate.setHours(parseInt(timeStringOrHours, 10), 0, 0, 0);
|
||||
// }
|
||||
|
||||
// return newDate;
|
||||
// };
|
||||
// // format date to 'HH:mm' time string required by the time picker
|
||||
// exports.formatTimeHHmm = function (input) {
|
||||
// // Check if the input is a string or a Date object
|
||||
// const date = (typeof input === 'string') ? new Date(input) : input;
|
||||
|
||||
// return date.toLocaleTimeString('en-US', {
|
||||
// hour12: false,
|
||||
// hour: '2-digit',
|
||||
// minute: '2-digit',
|
||||
// timeZone: 'Europe/Sofia'
|
||||
// }).substring(0, 5);
|
||||
// }
|
||||
|
||||
|
||||
// //parse 'HH:mm' time string to date object
|
||||
// exports.parseTimeHHmm = (timeString) => {
|
||||
// // If timeString is already a date, return it as is
|
||||
// if (timeString instanceof Date) {
|
||||
// return timeString;
|
||||
// }
|
||||
|
||||
// const [hours, minutes] = timeString.split(':');
|
||||
// const date = new Date();
|
||||
// date.setHours(hours);
|
||||
// date.setMinutes(minutes);
|
||||
// return date;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
exports.getTimeInMinutes = (dateOrTimestamp) => {
|
||||
const date = new Date(dateOrTimestamp);
|
||||
logger.debug("getTimeInMinutes: date = ", date);
|
||||
@ -782,8 +818,13 @@ exports.convertDatesToISOStrings = function (obj) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
// if (obj instanceof Date) {
|
||||
// return obj.toISOString();
|
||||
// }
|
||||
if (obj instanceof Date) {
|
||||
return obj.toISOString();
|
||||
// Convert the Date object to a Luxon DateTime in UTC
|
||||
const utcDate = DateTime.fromJSDate(obj, { zone: 'utc' });
|
||||
return utcDate.toISO(); // Output in UTC as ISO string
|
||||
}
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
@ -800,7 +841,29 @@ exports.convertDatesToISOStrings = function (obj) {
|
||||
|
||||
return obj;
|
||||
}
|
||||
function adjustDateForDST(date, timezone) {
|
||||
// Convert the date to the specified timezone
|
||||
let dateTime = DateTime.fromJSDate(date, { zone: timezone });
|
||||
|
||||
// Check if the original date is in DST
|
||||
const isOriginalDST = dateTime.isInDST;
|
||||
|
||||
// Check if the current date in the same timezone is in DST
|
||||
const isNowDST = DateTime.now().setZone(timezone).isInDST;
|
||||
|
||||
// Compare and adjust if necessary
|
||||
if (isOriginalDST && !isNowDST) {
|
||||
// If original date was in DST but now is not, subtract one hour
|
||||
dateTime = dateTime.minus({ hours: 1 });
|
||||
} else if (!isOriginalDST && isNowDST) {
|
||||
// If original date was not in DST but now is, add one hour
|
||||
dateTime = dateTime.plus({ hours: 1 });
|
||||
}
|
||||
|
||||
// Return the adjusted date as a JavaScript Date
|
||||
return dateTime.toJSDate();
|
||||
}
|
||||
exports.adjustDateForDST = adjustDateForDST;
|
||||
|
||||
// exports.getInitials = function (names) {
|
||||
// const parts = names.split(' '); // Split the full name into parts
|
||||
|
Reference in New Issue
Block a user