Moment-timezone import / duplication trap

chatgpt is telling me i have run into the classic moment-timezone import / duplication trap

Im getting the error: moment.tz is not a function
Here’s the relevant code:

const TZ = 'Europe/Oslo';
const startMonth = moment.tz(dateTimeValue, TZ).startOf('day');
const endMonth   = moment.tz(periodEnd,   TZ).endOf('day');
const startUnit  = moment(historikkEnhet.fra).tz(TZ).startOf('day');
const endUnit    = moment(historikkEnhet.til).tz(TZ).endOf('day');

The code ran once without error, but now im consistently getting the error. Anyone experienced this and know how ti fix it?

Hi @ole.sorheim,

I tried to reproduce the issue, but everything worked on my side. Could you double-check that the correct library is added? Just a quick reminder: the returned moment.js object needs to be converted into a Datetime data type, which you can do by calling .toJSON().

This is how I tested:

I used the Moment.js package, not Moment Timezone since it is Deprecated.
When using Moment.js I ran into several problems like the one above. All of these failed:
moment.min()
moment.max()
moment.tz()

In the function editor, it looks like all these functions exist. However, running the function fails with the error “moment. (…) is not a function”

Hi @ole.sorheim,

I double-checked how moment works inside Appfarm Create functions, and here’s the key point:

  • When you call moment(...) in a function, the App Time Zone is applied automatically. That means you don’t need (and can’t) call .tz(...) yourself.

  • There was a short period (around version 113, earlier this year) where .tz(...) looked like it worked, but that was actually a bug. It’s not supported anymore.

So your snippet should look like this instead:

const startMonth = moment(dateTimeValue).startOf(‘day’).toJSON();
const endMonth   = moment(periodEnd).endOf(‘day’).toJSON();
const startUnit  = moment(historikkEnhet.fra).startOf(‘day’).toJSON();
const endUnit    = moment(historikkEnhet.til).endOf(‘day’).toJSON();

If you really need manual timezone conversion different from the app’s timezone, update the app time zone under app variables as described here.

Regarding min/max: Only the instance methods (a.max(b), a.min(b)) are supported.

const a = moment("2025-09-01T10:00:00");
const b = moment("2025-09-05T15:00:00");

const latest   = a.max(b); 
const earliest = a.min(b);

return latest.toJSON();

Hope this clears it up!

Thanks!

Still have some questions. First why do you need .toJSON() ? Im not using it anywhere and the solution seems to work just fine. See the relevant parts of the code below:

const startMonth = moment(dateTimeValue);  // e.g. "2025-07-31T22:00:00.000Z" (Aug 1, 00:00 Oslo)
const endMonth   = moment(periodEnd);      // e.g. "2025-08-31T21:59:59.000Z" (Aug 31, 23:59:59 Oslo)

const startUnit  = moment(historikkEnhet.fra);
const endUnit    = moment(historikkEnhet.til);

// Clamp to the income month
const actualStart = startUnit.isAfter(startMonth) ? startUnit : startMonth;
const actualEnd   = endUnit.isBefore(endMonth)   ? endUnit   : endMonth;

if (actualEnd.isBefore(actualStart)) return 0;
const msPerDay = 24 * 60 * 60 * 1000;
const daysUnit = actualEnd.diff(actualStart, 'days');
const weeksUnit = parseFloat(((daysUnit + 1) / 7).toFixed(5));
const daysMonth = endMonth.diff(startMonth, 'days');

Hi @ole.sorheim,

We recommend using .toJSON() as outlined in the documentation to ensure the value is converted to the correct data type. While it may sometimes work without it, as you mentioned, skipping it can lead to issues. For example, in the min/max case, omitting .toJSON() results in this type of error:

To add to this, toJSON() is only required when returning a Moment value from a function. This is to ensure that the output of the function is a primitive value and not an object.

I’m getting messages saying that the instance methods are depricated.
Im also getting som funny results using these.

This aint right is it?

a = 2025-10-29T23:00:00.000Z
b = 2025-09-30T22:00:00.000Z
a.max(b) = b ???
    console.log("Before max()", temp_start, actualStart)
    temp_start = temp_start.max(actualStart)
    console.log("After max()", temp_start, actualStart)

a.max() seem to consistently return the object furthest back (i.e. how I would expect min() to work)

Did some further testing, and the only thing I got to work is the following:

temp_start = temp_start.max(temp_start, actualStart)

This seems very counterintuitive. Is this intended?

I can also add that I’m 99% sure this was not how it worked yesterday. Is it maybe related to some update? I was prompted to update in Create today

Hi!

I believe you first try was incorrect use of max(). This is defined here:

temp_start = temp_start.max(actualStart) always return actualStart, since you need to put the dates inside the paranthesis.

Hope that helps (and is the reason). This is not behaviour defined by Create, but by the momentjs library.