skip to Main Content

I’m using DayJS in my project. The user can enter some booking details, which are passed to a serverside function. This function should process the booking, but using the Dutch timezone.

No matter what I try, it keeps on using ‘en’ as locale. I’ve tried setting it globally, directly after importing the language file. Also I’ve tried to add it to every dayjs instance I create. Finally, I’ve put it all togheter, adding locale settings to every dayjs instance I have. No matter what, it doesn’t give me ‘nl’ as timezone. I left all code in my example below.

This is my serverside code:

import { PrismaClient } from "@prisma/client";
import { v4 as uuidv4 } from "uuid";
import dayjs from "dayjs";
import "dayjs/locale/nl";
import isSameOrBefore from "dayjs/plugin/isSameOrBefore.js";
import isSameOrAfter from "dayjs/plugin/isSameOrAfter.js";
import weekday from "dayjs/plugin/weekday.js";
dayjs.locale("nl");
dayjs.extend(isSameOrBefore);
dayjs.extend(isSameOrAfter);
dayjs.extend(weekday);

const createRepeatedBookingWeek = (data, body) => {
  return new Promise(async (resolve, reject) => {
    const prisma = new PrismaClient();
    const bookingGroup = uuidv4();
    dayjs.locale("nl");

    const writeActionlog = async () => {
      const performingUserEmail = body.auth.currentUser.email;

      const performingUser = await prisma.User.findUnique({
        where: { email: performingUserEmail },
        select: { id: true },
      });

      if (performingUser) {
        await prisma.ActionLog.create({
          data: {
            actionOfUser: { connect: { id: performingUser.id } },
            performedAction: {
              connect: { name: data.actionName },
            },
          },
        });

        await prisma.$disconnect();
        return true;
      } else {
        return {
          body: JSON.stringify({
            snackbar: {
              type: "error", //success || error || warning || info
              title: "Foutcode CRBW39",
              text: "De gebruiker is niet in de database gevonden.",
            },
          }),
        };
      }
    };

    const clashingBookings = [];

    const checkForOverlappingBookings = async (query) => {
      for (const room of body.details.rooms) {
        await prisma.Booking.findMany({
          where: {
            rooms: {
              some: {
                id: room.id,
              },
            },
            OR: query,
          },
        }).then((booking) => {
          booking.forEach((element) => {
            clashingBookings.push({ ...element, room: room });
          });
        });
      }
    };

    const excludedDates = [];
    if (body.details.excludedDates && body.details.excludedDates.length != 0) {
      body.details.excludedDates.map((d) => {
        excludedDates.push(dayjs(d).locale("nl"));
      });
    }

    const checkIfExcluded = (f, t) => {
      let value = false;
      excludedDates.map((ed) => {
        if (ed.isSame(f, "day") || ed.isSame(t, "day")) {
          value = true;
        }
      });

      return value;
    };

    if (
      !body.details ||
      body.details.name == "" ||
      body.details.dateFrom == "" ||
      body.details.dateTo == ""
    ) {
      return resolve({
        body: JSON.stringify({
          snackbar: {
            type: "error", //success || error || warning || info
            title: "Foutcode CRBW98",
            text: "Invoervelden mogen niet leeg zijn.",
          },
        }),
      });
    }

    dayjs.locale("nl");

    const bookingStart = dayjs(
      `${body.details.dateFrom} ${body.details.timeFrom}`,
      "YYYY-MM-DD HH:mm",
      "nl"
    )
      .locale("nl")
      .set("second", 0)
      .set("millisecond", 0);

    const bookingStartTS = "" + bookingStart.valueOf();
    const bookingStartOfDay = bookingStart.startOf("day");

    const bookingEnd = dayjs(
      `${body.details.dateTo} ${body.details.timeTo}`,
      "YYYY-MM-DD HH:mm",
      "nl"
    )
      .locale("nl")
      .set("second", 0)
      .set("millisecond", 0);

    const bookingEndTS = "" + bookingEnd.valueOf();

    const repeatEnd = dayjs(
      body.details.repeatOptions.repeatUntil,
      "YYYY-MM-DD",
      "nl"
    )
      .locale("nl")
      .set("hour", 23)
      .set("minute", 59)
      .set("second", 59)
      .set("millisecond", 999);

    const repeatEndTS = "" + repeatEnd.valueOf();

    const bookingDifference = bookingEndTS - bookingStartTS;
    let dayToCheck = dayjs(bookingStart).locale("nl");

    const orConditions = [];
    const dateRanges = [];

    try {
      while (dayToCheck.isSameOrBefore(repeatEnd)) {
        let firstDayOfWeek = dayToCheck.startOf("week").locale("nl");
        const lastDayOfWeek = dayToCheck.endOf("week").locale("nl");
        console.log("locale", dayjs.locale());
        console.log("firstDayOfWeek", firstDayOfWeek);

        while (firstDayOfWeek.isSameOrBefore(lastDayOfWeek)) {
          if (
            body.details.repeatOptions.repeatOn.includes(
              firstDayOfWeek.weekday()
            )
          ) {
            const shouldBeExcluded = checkIfExcluded(
              firstDayOfWeek,
              firstDayOfWeek
            );

            if (
              !shouldBeExcluded &&
              firstDayOfWeek.isSameOrAfter(bookingStartOfDay)
            ) {
              dateRanges.push(firstDayOfWeek);
            }
          }
          firstDayOfWeek = firstDayOfWeek.add(1, "day");
        }

        dayToCheck = dayToCheck.add(
          body.details.repeatOptions.interval,
          "week"
        );
      }

      // Loop through each date range
      dateRanges.forEach((dateRange) => {
        // Extract fromTS and toTS from the current date range
        const fH = body.details.timeFrom.slice(0, 2);
        const fI = body.details.timeFrom.slice(3, 5);
        const fromTS = dayjs(dateRange)
          .locale("nl")
          .set("hour", +fH)
          .set("minute", +fI)
          .valueOf();
        const toTS = dayjs(fromTS)
          .locale("nl")
          .add(bookingDifference, "ms")
          .valueOf();

        // Push into the OR conditions array
        orConditions.push({
          AND: [
            { tsFrom: { lte: "" + fromTS } },
            { tsTo: { gt: "" + fromTS } },
          ],
        });
        orConditions.push({
          AND: [{ tsFrom: { lt: "" + toTS } }, { tsTo: { gte: "" + toTS } }],
        });
        orConditions.push({
          AND: [{ tsFrom: { gte: "" + fromTS } }, { tsTo: { lte: "" + toTS } }],
        });
      });

      await checkForOverlappingBookings(orConditions);

      if (clashingBookings.length > 0) {
        let clashDates = "";
        let i = 1;
        clashingBookings.map((b) => {
          clashDates += `${b.dateFd}-${b.dateFm}-${b.dateFy} (${b.name})`;
          if (i != clashingBookings.length) {
            clashDates += ", ";
          }
          i++;
        });

        return resolve({
          body: JSON.stringify({
            snackbar: {
              type: "error", //success || error || warning || info
              title: "Foutcode CRBW220",
              text: `De reservering heeft een overlap met ${
                clashingBookings.length == 1
                  ? "een bestaande boeking"
                  : "bestaande boekingen"
              } op ${clashDates}.`,
            },
          }),
        });
      } else {
        (async () => {
          for (const dateRange of dateRanges) {
            const fH = body.details.timeFrom.slice(0, 2);
            const fI = body.details.timeFrom.slice(3, 5);

            //   Convert dayjs back to prisma format:
            const fromTS = dayjs(dateRange)
              .locale("nl")
              .set("hour", +fH)
              .set("minute", +fI)
              .valueOf();
            const toTS = dayjs(fromTS)
              .locale("nl")
              .add(bookingDifference, "ms")
              .valueOf();

            const newFrom = dayjs(fromTS).locale("nl");
            const newTo = dayjs(toTS).locale("nl");

            let newFday = newFrom.get("date");
            let newFmonth = newFrom.get("month") + 1;
            let newFyear = newFrom.get("year");
            let newTday = newTo.get("date");
            let newTmonth = newTo.get("month") + 1;
            let newTyear = newTo.get("year");

            // create the booking
            await prisma.Booking.create({
              data: {
                name: body.details.name,
                description: body.details.description,
                tsFrom: "" + fromTS,
                dateFd: `${String(newFday).padStart(2, "0")}`,
                dateFm: `${String(newFmonth).padStart(2, "0")}`,
                dateFy: "" + newFyear,
                dateFh: body.details.timeFrom.slice(0, 2),
                dateFi: body.details.timeFrom.slice(3, 5),
                tsTo: "" + toTS,
                dateTd: `${String(newTday).padStart(2, "0")}`,
                dateTm: `${String(newTmonth).padStart(2, "0")}`,
                dateTy: "" + newTyear,
                dateTh: body.details.timeTo.slice(0, 2),
                dateTi: body.details.timeTo.slice(3, 5),
              },
            }).then(async () => {
              await prisma.$disconnect();
            });

            // Pause the loop
            await new Promise((resolve) => setTimeout(resolve, 300));
          }
        })();
      }

      await writeActionlog();

      return resolve({
        body: JSON.stringify({
          snackbar: {
            type: "success", //success || error || warning || info
            title: "Succes",
            text: "De reserveringen zijn aangemaakt.",
          },
        }),
      });
    } catch (error) {
      console.log(error);
      await prisma.$disconnect();
      return {
        body: JSON.stringify({
          snackbar: {
            type: "error", //success || error || warning || info
            title: "Foutcode CRBW320",
            text: "De reservering kon niet worden aangemaakt.",
          },
        }),
      };
    }
  });
};

export default createRepeatedBookingWeek;

UPDATE
I’ve created a minified version, still the same issue

import { PrismaClient } from "@prisma/client";
import checkAuth from "./utils/auth";
import dayjs from "dayjs";
import "dayjs/locale/nl";

dayjs.locale("nl");
export default defineEventHandler(async (event) => {
  const prisma = new PrismaClient();
  const body = await readBody(event);

  let response = (async (result) => {
    // Else perform main logic here

    try {
      const el = dayjs();
      console.log("el: ", el);

      return {
        body: JSON.stringify({
          snackbar: {
            type: "success", //success || error || warning || info
            title: "Succes",
            text: "De wijzigingen zijn opgeslagen.",
          },
        }),
      };
    } catch (error) {
      console.log(error);

      return {
        body: JSON.stringify({
          snackbar: {
            type: "error", //success || error || warning || info
            title: "---",
            text: "De wijzigingen konden niet worden opgeslagen.",
          },
        }),
      };
    }
  })();

  return response;
});

Also here, el is returning ‘en’ as locale.

2

Answers


  1. Chosen as BEST ANSWER

    I think I found the solution.

    When exploring the dayjs folder in node_modules, I found out that the locale method is expecting three parameters. So I changed my code to

    const el = dayjs().locale("nl", {}, true);
    

    instead of

    const el = dayjs().locale("nl");
    

    and this creates a Dutch dayjs object.

    When reading the docs, only the not working version (with only 1 param) is documented. This should be updated!


  2. Reading the documentation here you change the locale locally:

    require('dayjs/locale/de')
    dayjs().locale('de').format() // use loaded locale locally
    

    In your context it will be nl instead on de in the example. As you can see you have to include the correct locale before using it

    If you want to change it globally you can see here and you will notice you just need to do the require part

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search