# Asana DateTime CSV Preflight (`atesen-software/asana-datetime-csv-preflight`) Actor

Validate supplied custom-date CSV rows, reject DST ambiguity and return UTC previews. Offline; no Asana login, task updates or executable API requests.

- **URL**: https://apify.com/atesen-software/asana-datetime-csv-preflight.md
- **Developed by:** [Atesen Software](https://apify.com/atesen-software) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 date-time preview rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Asana DateTime CSV Preflight do?

Validate a supplied **CSV of task IDs, custom-field IDs and local date-times**, then produce a UTC preview with explicit timezone offsets. This data-processing Actor helps operators prepare date-time values for [Asana custom fields](https://developers.asana.com/docs/custom-fields-guide). It does not connect to Asana, import tasks, update fields or produce executable API requests.

### Why check date-times before a migration?

A date-only value, a daylight-saving gap and a repeated local clock time need different handling. This preflight rejects invalid or ambiguous inputs instead of silently choosing a timezone. Exact IDs remain strings, identical duplicates are marked, conflicting duplicates reject the batch, and free-text notes are omitted from results.

This is a preparation step, not a replacement for the native importer or an authenticated migration tool. Asana's community has documented date-time CSV import limitations; check its current capabilities before planning a migration. This Actor cannot establish whether an ID exists, belongs to a project, identifies a writable date field, or has the required permissions and plan. Its UTC output is not a tenant-tested write payload.

### How to use the preflight

1. Run **Demo** to inspect five synthetic rows. The identifiers are invented.
2. Select **Check** and supply your authorized CSV plus the project GID. Both are required for custom input; sample rows are never mixed into your file.
3. Read the dataset and final `RECEIPT`. Every result remains `executable: false`.
4. Verify actual Asana metadata, permissions and current field values in your chosen migration workflow before changing anything.

CSV headers are `task_gid,custom_field_gid,local_datetime,timezone`, with optional `offset,note`. Use one custom-field GID per run. A local timestamp must include whole seconds, such as `2026-12-01T12:00:00`; timezone must be an IANA name such as `Europe/Berlin`, or `UTC`. An optional offset is `Z` or `+/-HH:MM`. Repeated daylight-saving times require a matching explicit offset; nonexistent local times are rejected even with an offset. Date-only and fractional-second input are unsupported.

Limits are 1,000 CSV rows, 1,000,000 CSV bytes, 4,096 characters per cell and a 2,000,000-byte total JSON input. Invalid rows reject the entire batch before any result is charged. See the Input tab for the form. No password, API token, proxy or external AI service is needed.

### What data does the Actor return?

| Field | Meaning |
|---|---|
| `row` | Original one-based CSV data-row number |
| `task_gid`, `custom_field_gid` | Supplied exact identifiers, not verified against Asana |
| `proposed_date_time` | Normalized UTC instant ending in `Z` |
| `local_with_offset`, `timezone` | Local value with resolved offset and supplied timezone |
| `status` | UTC preview requiring live verification, or identical-input duplicate |
| `executable` | Always false |
| `inputKind` | Synthetic demonstration or supplied CSV |

Download the dataset as JSON, CSV, Excel or other formats supported by Apify. `RECEIPT` is a JSON object with delivered rows, input-row count and `budgetLimited`. `STATE` records completion and acknowledged pushes. An interrupted push may have committed before acknowledgement, so its count is a lower bound, not exact dataset reconciliation. `ERROR` uses safe error types and row codes without echoing arbitrary exception messages or notes.

### How much does it cost?

The result fee is **$2 per 1,000 delivered date-time rows** ($0.002 per row). Five demonstration rows cost up to $0.01 in result fees. Identical-input duplicate rows are still delivered rows and are charged. Rejected batches produce no result fee; normal platform usage may still apply according to the run's pricing details. A demonstration is not a free trial or a live Asana acceptance test.

**API and CLI callers must set `maxTotalChargeUsd` explicitly for each run.** A configured default of $0.01 does not guarantee that every launch method forwards that cap. Inspect the actual run options. This cap governs event charges, not an independent guarantee about every platform cost. Use 128 MB and a short timeout for small files.

When the cap cannot cover the whole file, the Actor stops at the affordable row boundary and writes a `BUDGET_LIMITED` partial receipt. Dataset and receipt contain only delivered rows; uncharged row contents are not included in reports. Zero budget produces zero rows. Always check `deliveredRows`, `inputRows`, `budgetLimited` and final `STATE.completed` before treating a run as finished.

### FAQ and support

#### Will this fix or import my Asana CSV?

It validates supported fields and returns UTC previews. It does not change Asana or emit an import-ready native CSV. Do not upload the output as though it were an accepted Asana import template.

#### Which timezone rules are used?

The release pins the `tzdata` package to 2026.6. Results follow that database; later timezone-law changes may require an Actor update. A missing timezone is an error, never an implicit UTC fallback.

#### Can I submit credentials or sensitive notes?

No credentials are needed. Supply only data you are authorized to process, and omit unnecessary personal information. Notes are discarded, but the submitted INPUT is still stored by the platform under its normal run-storage rules. Use the Issues tab for reproducible problems with synthetic examples and the API tab for programmatic access.

# Actor input Schema

## `mode` (type: `string`):

Demo uses5synthetic rows. Select Check to process your supplied authorized CSV; no sample values fill missing custom input.

## `csv` (type: `string`):

UTF8CSV: task_gid,custom_field_gid,local_datetime,timezone; optionaloffset,note. One field perrun;1000rows/1000000bytes. Names are not IDs. Notes are omitted.

## `projectGid` (type: `string`):

Exact positive decimal project identifier. Required for Check. Syntax only; membership/existence is not verified. Demo identifier3001is invented.

## Actor input object example

```json
{
  "mode": "demo",
  "csv": "task_gid,custom_field_gid,local_datetime,timezone,offset\n1001,2001,2026-12-01T12:00:00,Europe/Berlin,\n1002,2001,2026-12-01T12:00:00,America/New_York,\n1003,2001,2026-12-01T12:00:00,Asia/Kathmandu,\n1004,2001,2026-10-25T02:30:00,Europe/Berlin,+01:00\n1005,2001,2026-10-25T02:30:00,Europe/Berlin,+02:00\n",
  "projectGid": "3001"
}
```

# Actor output Schema

## `dataset` (type: `string`):

Onlydeliveredrowchecks; no HTTPdrafts.

## `receipt` (type: `string`):

CheckbudgetLimited and deliveredRows.

## `state` (type: `string`):

Checkcompleted beforeacceptance.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "csv": `task_gid,custom_field_gid,local_datetime,timezone,offset
1001,2001,2026-12-01T12:00:00,Europe/Berlin,
1002,2001,2026-12-01T12:00:00,America/New_York,
1003,2001,2026-12-01T12:00:00,Asia/Kathmandu,
1004,2001,2026-10-25T02:30:00,Europe/Berlin,+01:00
1005,2001,2026-10-25T02:30:00,Europe/Berlin,+02:00`,
    "projectGid": "3001"
};

// Run the Actor and wait for it to finish
const run = await client.actor("atesen-software/asana-datetime-csv-preflight").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "csv": """task_gid,custom_field_gid,local_datetime,timezone,offset
1001,2001,2026-12-01T12:00:00,Europe/Berlin,
1002,2001,2026-12-01T12:00:00,America/New_York,
1003,2001,2026-12-01T12:00:00,Asia/Kathmandu,
1004,2001,2026-10-25T02:30:00,Europe/Berlin,+01:00
1005,2001,2026-10-25T02:30:00,Europe/Berlin,+02:00
""",
    "projectGid": "3001",
}

# Run the Actor and wait for it to finish
run = client.actor("atesen-software/asana-datetime-csv-preflight").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "csv": "task_gid,custom_field_gid,local_datetime,timezone,offset\\n1001,2001,2026-12-01T12:00:00,Europe/Berlin,\\n1002,2001,2026-12-01T12:00:00,America/New_York,\\n1003,2001,2026-12-01T12:00:00,Asia/Kathmandu,\\n1004,2001,2026-10-25T02:30:00,Europe/Berlin,+01:00\\n1005,2001,2026-10-25T02:30:00,Europe/Berlin,+02:00\\n",
  "projectGid": "3001"
}' |
apify call atesen-software/asana-datetime-csv-preflight --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,atesen-software/asana-datetime-csv-preflight"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/mLyrTqcpcc2l12h8G/builds/rANA2ZglCXBTkOspI/openapi.json
