Problem with time zone offset in google calendar

Describe the problem/error/question

i use n8n on digital ocean and try google calendar template from n8n google calendar docs. I live in Kyiv and when i ask through the chat make event for example on 08:00 ai agent make it in 3 hours on 11:00. There are shift on 3 hours. I make this google calendar assistant for client who live on Bali, how i could make this assistant do well for all time zone. For example he move to Europe or to USA i want that this assistant work well for every time zone. What i should to do?

Thank you)

What is the error message (if any)?

Please share your workflow

(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow.)
{
  "nodes": [
    {
      "parameters": {
        "options": {}
      },
      "id": "94363d80-25e4-4105-97da-62a838d5c8d4",
      "name": "When chat message received",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        100,
        380
      ],
      "webhookId": "5308edc9-738b-4aae-a789-214e2392579a",
      "typeVersion": 1.1
    },
    {
      "parameters": {
        "model": "gpt-4.1-mini",
        "options": {}
      },
      "id": "2e054553-d766-4bc8-8071-cb934ce395a3",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        540,
        1200
      ],
      "typeVersion": 1,
      "credentials": {
        "openAiApi": {
          "id": "cOJeDyHb0VCS1yDk",
          "name": "OpenAi account"
        }
      }
    },
    {
      "parameters": {},
      "id": "941e1776-efe7-4d59-8133-74022b3bd9d1",
      "name": "Window Buffer Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        960,
        1200
      ],
      "typeVersion": 1.3
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "Use this tool when you’re asked to retrieve events data.",
        "operation": "getAll",
        "calendar": {
          "__rl": true,
          "value": "[email protected]",
          "mode": "list",
          "cachedResultName": "Работа"
        },
        "options": {
          "timeMin": "={{ $fromAI('start_date') }}",
          "timeMax": "={{ $fromAI('end_date') }}"
        }
      },
      "id": "7f3d7ece-d820-4dfe-9054-08b00323b96d",
      "name": "Google Calendar - Get Events",
      "type": "n8n-nodes-base.googleCalendarTool",
      "position": [
        1340,
        1180
      ],
      "typeVersion": 1.2,
      "credentials": {
        "googleCalendarOAuth2Api": {
          "id": "DuZTlVnG1Cwac9MD",
          "name": "Google Calendar account"
        }
      }
    },
    {
      "parameters": {
        "descriptionType": "manual",
        "toolDescription": "Use this Google Calendar tool when you are asked to create an event.",
        "calendar": {
          "__rl": true,
          "value": "[email protected]",
          "mode": "list",
          "cachedResultName": "Работа"
        },
        "start": "={{ $fromAI('start_date') }} ",
        "end": "={{ $fromAI('end_date') }} ",
        "useDefaultReminders": false,
        "additionalFields": {
          "attendees": [],
          "description": "={{ $fromAI('event_description') }} ",
          "summary": "={{ $fromAI('event_title') }} "
        }
      },
      "id": "88e289ee-d46a-47dc-9e66-ae08505bf53b",
      "name": "Google Calendar - Create events",
      "type": "n8n-nodes-base.googleCalendarTool",
      "position": [
        1760,
        1180
      ],
      "typeVersion": 1.2,
      "credentials": {
        "googleCalendarOAuth2Api": {
          "id": "DuZTlVnG1Cwac9MD",
          "name": "Google Calendar account"
        }
      }
    },
    {
      "parameters": {
        "content": "## Chat trigger - When a message is received\n\nThis node is the **entry point of the workflow**.  \nIt triggers the workflow whenever a message is sent to the **chat interface**.\n\nOptions with n8n:\n- **Embed the chat interface** anywhere you want.\n- Use a **webhook node** instead of this node to connect with interfaces like **[Streamlit](https://docs.streamlit.io/develop/tutorials/llms/build-conversational-apps)** or **[OpenWebUI](https://docs.openwebui.com/)**.\n- Use nodes for communication platforms (**Slack**, **Teams**, **Discord**, etc.) if you know how to configure them.\n",
        "height": 560,
        "width": 320,
        "color": 7
      },
      "id": "96d1c296-4e54-4431-9825-c82423955957",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Tools Agent - Calendar AI Agent\n\nThis **node** configures the **AI agent** for interaction with Google Calendar.  \nIt includes the following features:\n\n- A **prompt source**: This is the user message derived from the chat input of the preceding node (`When chat message is received`).\n- A **system message**: This defines the system prompt to guide the AI agent's behavior. It incorporates the variable `{{ DateTime.local().toFormat('cccc d LLLL yyyy') }`, allowing the AI agent to determine the current date and interact with Google Calendar accordingly. For example, the agent can understand a request like \"Create an event called 'n8n workflow review' for next Tuesday.\"\n\n\nn8n nodes come with built-in **guardrails**, ensuring that if the user requests tasks outside the AI agent's setup, it may not function as intended. (Feel free to test it!)\n",
        "height": 560,
        "width": 1520,
        "color": 7
      },
      "id": "9768bad4-dffa-4f54-97fa-66bd78f6a099",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        440,
        0
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.chatInput }}",
        "options": {
          "systemMessage": "=You are a Google Calendar assistant.\nYour primary goal is to assist the user in managing their calendar effectively using two tools: Event Creation and Event Retrieval. Always base your responses on the current date: \n{{ DateTime.local().toFormat('cccc d LLLL yyyy') }}.\nGeneral Guidelines:\nIf the user's initial message is vague (e.g., \"hello\" or a generic greeting) or does not specify a request, explain your capabilities clearly:\nExample: \"Hello! I can help you manage your Google Calendar. You can ask me to create an event or retrieve event data. What would you like me to do?\"\nIf the user specifies a request in their first message, begin preparing to use the appropriate tool:\nFor event creation, gather necessary details like start date, end date, title, and description.\nFor event retrieval, ask for the date range or time period they want to query.\nTool: Event Creation\nWhen asked to create an event:\n\nRequest the start and end dates/times from the user.\nDate format: YYYY-MM-DD HH:mm:ss\nCollect the following information:\nstart_date: Exact start date and time of the event.\nend_date: Exact end date and time of the event.\nevent_title: Event title in uppercase. Suggest one if not provided.\nevent_description: Generate a brief description and present it for confirmation.\nTool: Event Retrieval\nWhen asked to retrieve events:\n\nAsk for the date range or period they are interested in. Examples:\nFor \"last week,\" retrieve events from Monday of the previous week to Friday of the same week.\nFor \"today,\" use the current date.\nFormat the date range:\nstart_date: Start date and time in YYYY-MM-DD HH:mm:ss.\nend_date: End date and time in YYYY-MM-DD HH:mm:ss.\nKey Behaviors:\nClarity: Provide a clear and helpful introduction when the user's request is unclear.\nValidation: Confirm details with the user before finalizing actions.\nAdaptation: Handle varying levels of detail in requests (e.g., \"Add a meeting for next Monday morning\" or \"Retrieve my events for this weekend\").\nProactivity: Offer suggestions to fill in missing details or clarify ambiguous inputs.\nLanguage Matching: Ensure all interactions, including event titles, descriptions, and messages, are in the user's language to provide a seamless experience."
        }
      },
      "id": "5ff22c95-0000-4825-aa7e-68e564fbb23b",
      "name": "Calendar AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        960,
        380
      ],
      "typeVersion": 1.7
    },
    {
      "parameters": {
        "content": "## OpenAI chat model\n\nThis node specifies the chat model used by the agent.  \nIn the template, the **default LLM is gpt-4o** for its high relevance.\n\nOther options:\n- You can **try gpt-4o-mini**, which is more cost-effective.\n- You can also choose **other LLM providers besides OpenAI**, but make sure the LLM you select **supports tool-calling**.\n",
        "height": 720,
        "width": 320,
        "color": 5
      },
      "id": "74bacce0-6a09-4bd9-8d2b-ba664b961d6f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        440,
        620
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Window buffer memory\n\nThis node manages the **memory** of the agent, specifically the **context window length** for chat history.  \nThe default is set to 5 messages.\n\nNote:  \nThe **memory** is **temporary**. If you want to **store conversations with the agent**, you should use other nodes like **Postgres chat memory**.  \nThis can be easily set up with services like **[Supabase](https://supabase.com/)**.\n",
        "height": 720,
        "width": 320,
        "color": 5
      },
      "id": "c5bf4a36-03b2-4dbd-ba0e-29d473321720",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        840,
        620
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Google Calendar - Get Events\n\nThis sub-node is a tool used by the AI agent.  \nIts purpose is to **retrieve events based on the user input**.  \nFor example: *\"Can you give me the events from last week about internal process ?\"*\n\nThe AI agent is designed to **use this tool only** when it has a **date range**.  \nIf the user hasn’t provided a date range, the **AI agent will ask the user** for it.\n\nThe **variables** `{{ $fromAI('start_date') }}` and `{{ $fromAI('end_date') }}` are **dynamically filled by the AI**.\n",
        "height": 720,
        "width": 320,
        "color": 5
      },
      "id": "6583a6b3-87b2-4a22-aeac-fa15c16b6dea",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1240,
        620
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Google Calendar - Create Events\n\nThis sub-node is a tool used by the AI agent.  \nIts purpose is to **create events based on the user input**.  \nFor example: \"Can you create an event 'Quarter revenue meeting' on [date] from [hour] to [hour] ?\"\n\nThe AI agent is designed to **use this tool only** when it has a **date range**.  \nIf the user hasn’t provided a **date range**, the AI agent will **ask the user** for it.  \nThe variables `{{ $fromAI('start_date') }}` and `{{ $fromAI('end_date') }}` are dynamically filled by the AI.\n\nBefore creating the event, the AI agent will **confirm with the user** if the **title** and **description** of the event are correct.  \nThe variables used for this are:\n- `{{ $fromAI('event_title') }}`\n- `{{ $fromAI('event_description') }}`\n",
        "height": 720,
        "width": 320,
        "color": 5
      },
      "id": "e40da347-25d2-4fd1-a0be-a54b9cd88ba6",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1640,
        620
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Having fun with it ? Here’s how to level up this AI agent !  \n\nThis workflow demonstrates **how easily you can set up an AI agent to call tools** for you using **n8n**.  \nThe tasks here are **useful but very basic**.  \n\nIf you want to **enhance the tool-calling capabilities**, consider the following:\n\n- Explore the **\"options\"** in the Google Calendar nodes to see additional features you can use.  \n  For example, let the AI agent add attendees to events it creates.\n\n- Implement the AI agent with your **teammates and link it to each calendar**.  \n  Use a `{{ $fromAI('') }}` variable for the calendar field and refine the prompts to suit your needs.\n\n- Add **more actions** for the AI agent to perform with the **Google Calendar API**, expanding its functionality.\n",
        "height": 380,
        "width": 720,
        "color": 4
      },
      "id": "9e3e6900-bfda-46a3-bf03-6655e8105855",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1240,
        1380
      ],
      "typeVersion": 1
    }
  ],
  "connections": {
    "When chat message received": {
      "main": [
        [
          {
            "node": "Calendar AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Calendar AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Window Buffer Memory": {
      "ai_memory": [
        [
          {
            "node": "Calendar AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Google Calendar - Get Events": {
      "ai_tool": [
        [
          {
            "node": "Calendar AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Google Calendar - Create events": {
      "ai_tool": [
        [
          {
            "node": "Calendar AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "b030d855f4155c47945573a7a9e77cc79230f61680495570418f0b9ca831da8a"
  }
}

Share the output returned by the last node

Information on your n8n setup

  • n8n version: - 1.93
  • Database (default: SQLite):
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app): - Docker->Digitalocean
  • Operating system:
1 Like

Hey,

You should be able to set this as an env var, and restart docker, it’s probably using the timezone of the server digitalocean is using.

export GENERIC_TIMEZONE=Europe/Berlin

But that seems like you want to change it, you could probably use the ai agent to convert timezones,

So somewhere in ure flow, you convert their location time to server time, to store maybe? you can use a table for current location from them either via the ai agent or stored data, u can add the code node, and the location into it, and produce there timestamp, then u can adjust the time stored via the ai agent, I guess you could even add this as a tool, for the ai agent.

1 Like

It happend to me too. It was with baserow tho.

My n8n installation is specficed with my local timezone but it was returning UTC time. Which is probably what happend to you.

If you haven’t set your timezone as @King_Samuel_David mentioned, it may fix your problem. For me it unfortunately didn’t work, I “fixed” it by adding a expression in the later outputs to convert to my local time.

1 Like

btw u can set timezone based on workflow too it seems I just found


if u go to workflow settings that might help further too :slight_smile:

Change settings of workflow - This way is not working for me and im wondering ((((

This one is not working for me too :frowning: i have changed but still have shift 3 hours