# Working with Dates and Times

Google Ads scripts often need to work with dates and times. Common use cases
include retrieving reports for a specific date range, scheduling campaigns or
ad groups to run at specific times, and outputting to a spreadsheet the time
the script last ran. This guide describes important concepts, common pitfalls,
and recommended approaches when working with dates and times in Google Ads scripts.

## Basic concepts

To work with dates and times in Google Ads scripts, use JavaScript's built-in
date object. A JavaScript date object represents a particular moment in time.
There are several ways to create a new date object:  

    // Create a date object for the current date and time.
    const now = new Date();

    // Create a date object for a past date and time using a formatted string.
    const date = new Date('February 17, 2025 13:00:00 -0500');

    // Create a copy of an existing date object.
    let copy = new Date(date);

New scripts users are often confused by how date objects handle time zones. A
natural but **incorrect** way to think of a date object is as *the time on a
clock in a single time zone* . For example, in the snippet before, some users
mistakenly assume that `date` is valid only in one time zone, namely the
time zone with a -5 hours offset that was used to create it. In that mistaken
view, `date` would need to be "converted" to be used in other time zones.

Instead, the **correct** way to think about a date object is as a particular
moment in time independent of any time zone. Although a particular moment is
shown differently on clocks in different time zones, it is the same moment. For
example, consider this snippet:  

    // Create two date objects with different times and time zone offsets.
    const date1 = new Date('February 17, 2025 13:00:00 -0500');
    const date2 = new Date('February 17, 2025 10:00:00 -0800');

    // getTime() returns the number of milliseconds since the beginning of
    // January 1, 1970 UTC.
    // True, as the dates represent the same moment in time.
    console.log(date1.getTime() == date2.getTime());

    // False, as the dates are separate objects, though they happen to
    // represent the same moment in time.
    console.log(date1 == date2);

| **Note:** Internally, JavaScript represents a date object as the number of milliseconds since January 1, 1970 UTC.

Since a date object represents a particular moment in time, it does not need to
be "converted" across time zones. Instead, it can be rendered as a string that
is *formatted* for a particular time zone.

To render a date as a string with a particular format and time zone, use
[`Utilities.formatDate(date, timeZone, format)`](https://developers.google.com/apps-script/reference/utilities/utilities#formatdatedate-timezone-format).
For example:  

    const date = new Date('February 17, 2025 13:00:00 -0500');

    // February 17, 2025 13:00:00 -0500
    console.log(Utilities.formatDate(date, 'America/New_York', 'MMMM dd, yyyy HH:mm:ss Z'));

    // February 17, 2025 10:00:00 -0800
    console.log(Utilities.formatDate(date, 'America/Los_Angeles', 'MMMM dd, yyyy HH:mm:ss Z'));

    // 2025-02-17T18:00:00.000Z
    console.log(Utilities.formatDate(date, 'Etc/GMT', 'yyyy-MM-dd\'T\'HH:mm:ss.SSS\'Z\''));

These examples specified the time zone directly using a
[timezone ID](https://developers.google.com/google-ads/api/reference/data/codes-formats#timezone-ids).
To retrieve the time zone associated with the Google Ads account running your
script, use
[`AdsApp.currentAccount().getTimeZone()`](https://developers.google.com/google-ads/scripts/docs/reference/adsapp/adsapp_account#getTimeZone).

## Common pitfalls

Here are some common pitfalls that occur with dates.

### Default time zone when logging a date object

When directly logging a date object using `Logger.log()`, it is rendered using
a default format and time zone. For example:  

    const date = new Date('February 17, 2025 13:00:00 -0500');

    // Mon Feb 17 10:00:00 GMT-08:00 2025
    console.log(date);

The default time zone is America/Los_Angeles (Pacific time), *regardless of the
time zone associated with the Google Ads account* . If you would like to render
the date object as a string using a custom format and time zone for logging or
other purposes, always use
[`Utilities.formatDate(date, timeZone, format)`](https://developers.google.com/apps-script/reference/utilities/utilities#formatdatedate-timezone-format).

### Default time zone when creating a date object

When creating a date object using a string that does *not* provide a time zone
offset, the time zone is assumed to be America/Los_Angeles (Pacific time),
*regardless of the time zone associated with the Google Ads account*. For
example:  

    // Create a date without specifying the time zone offset.
    const date = new Date('February 17, 2025 13:00:00');

    // Mon Feb 17 13:00:00 GMT-08:00 2025
    console.log(date);

When creating a date object using a string, always include a time zone offset to
ensure the date object represents the moment in time you actually want.

### Default time zone in date object methods

JavaScript date objects have several methods that assume a default time zone,
such as:

- `getFullYear()`
- `getMonth()`
- `getDate()`
- `getDay()`
- `getHours()`
- `getMinutes()`

This also includes these methods' `set___()` equivalents (for example,
`setMonth()`), and `getTimezoneOffset()`.

In Google Ads scripts, the default time zone is America/Los_Angeles (Pacific
time), *regardless of the time zone associated with the Google Ads account*.
Therefore, unless your Google Ads account is in this time zone, you should
generally avoid using these methods.

To get the year, month, date, day, hours, or minutes for a date object in your
account's time zone, use
[`Utilities.formatDate(date, timeZone, format)`](https://developers.google.com/apps-script/reference/utilities/utilities#formatdatedate-timezone-format)
with a format specifying the part of the date or time you want, and use
[`AdsApp.currentAccount().getTimeZone()`](https://developers.google.com/google-ads/scripts/docs/reference/adsapp/adsapp_account#getTimeZone)
to get your account's time zone.

### Creating a date object from a formatted date string

You can create a date object by passing a formatted date string to the date
constructor. For example:  

    const date = new Date('February 17, 2025 13:00:00 -0500');

The constructor can only parse certain date string formats. To make sure your
date string is parsed correctly, always provide it in the `MMMM dd, yyyy
HH:mm:ss Z` format.

For example, to construct a date object for noon today in the current account's
time zone:  

    const now = new Date();
    const timeZone = AdsApp.currentAccount().getTimeZone();
    const noonString = Utilities.formatDate(now, timeZone, 'MMMM dd, yyyy 12:00:00 Z');
    const noon = new Date(noonString);

Don't use the 'z' pattern to create date strings that will be passed to a date
constructor, as the constructor won't always be able to parse it. Only use
the 'Z' pattern.

## Date math

Some scripts need to perform simple math with dates, such as finding a date X
days before or after a given date. When performing date math, use `getTime()`.
Calling `getTime()` on a date object returns the number of milliseconds since
the beginning of January 1, 1970 UTC. You can perform math on this value, then
apply the new value to a date object using `setTime()` or providing it as a
parameter when creating a new date object.

For example:  

    const MILLIS_PER_DAY = 1000 * 60 * 60 * 24;
    const now = new Date();
    const yesterday = new Date(now.getTime() - MILLIS_PER_DAY);

In this example, `yesterday` is exactly 24 hours ago.

## Reporting

When retrieving a report using
[`AdsApp.search()`](https://developers.google.com/google-ads/scripts/docs/features/reports#search_example),
the [GAQL query](https://developers.google.com/google-ads/api/docs/query/overview) requires dates to be
specified in the format `yyyy-MM-dd` (for example, `2025-06-30` would be
June 30, 2025).

Likewise, the `getStatsFor()` method available on many Google Ads scripts
objects requires dates to be specified in the same format. Use
[`Utilities.formatDate(date, timeZone, format)`](https://developers.google.com/apps-script/reference/utilities/utilities#formatdatedate-timezone-format)
to format a date object in this format.

For example, to retrieve a report from one to three days ago:  

    const MILLIS_PER_DAY = 1000 * 60 * 60 * 24;
    const now = new Date();
    const from = new Date(now.getTime() - 3 * MILLIS_PER_DAY);
    const to = new Date(now.getTime() - 1 * MILLIS_PER_DAY);

    const timeZone = AdsApp.currentAccount().getTimeZone();
    const results = AdsApp.search(
        'SELECT campaign.name, metrics.clicks' +
        'FROM campaign ' +
        'WHERE segments.date BETWEEN ' +
        Utilities.formatDate(from, timeZone, 'yyyy-MM-dd') + ' AND ' +
        Utilities.formatDate(to, timeZone, 'yyyy-MM-dd'));

## Spreadsheets

Google Ads scripts often write output to a spreadsheet, including date objects.
When setting a cell in a spreadsheet by passing a date object, the
spreadsheet's time zone is used to interpret that date. For example, suppose we
have a spreadsheet whose time zone is set to Pacific Time:  

    // Suppose today is February 17, 2025 13:00:00 -0500 (Eastern Time)
    const now = new Date();
    spreadsheet.getRange('A1').setValue(now);

The value in A1 will be 17-Feb-25 10:00:00.

To ensure date objects are written to a spreadsheet as you expect, set the
spreadsheet's time zone to match your Google Ads account's time zone:  

    spreadsheet.setSpreadsheetTimeZone(AdsApp.currentAccount().getTimeZone());

You can also [set a spreadsheet's time manually](https://support.google.com/docs/answer/58515).