This document describes how start/end dates are synchronized between AniList and MyAnimeList.
Both AniList and MAL track two dates per entry:
- Start date — when the user started watching/reading
- End date — when the user finished watching/reading
Dates are synced in both directions:
- Forward (AniList -> MAL): dates flow via
GetUpdateOptions()usingmal.StartDate/mal.FinishDate - Reverse (MAL -> AniList): dates flow via GraphQL
SaveMediaListEntrymutation usingFuzzyDateInput
| Source date | Target date | Action |
|---|---|---|
| nil | nil | Nothing to do |
| nil | set | Skip — don't clear target date |
| set | nil | Sync date to target |
| same | same | No update needed |
| different | different | Update target with source date |
Key principle: nil source dates are never sent to avoid clearing manually-set dates on the target service.
The end date (FinishedAt / completedAt) is only sent when status is COMPLETED. This prevents prematurely setting a finish date for entries that are still in progress.
| Status | startedAt sent? | completedAt sent? |
|---|---|---|
| WATCHING | yes (if set) | no |
| COMPLETED | yes (if set) | yes (if set) |
| ON_HOLD | yes (if set) | no |
| DROPPED | yes (if set) | no |
| PLAN_TO_* | yes (if set) | no |
input FuzzyDateInput {
year: Int
month: Int
day: Int
}Dates are sent as a map: {"year": 2023, "month": 6, "day": 15}. When a date is nil, the variable is omitted from the mutation entirely (not sent as null).
Dates are formatted as YYYY-MM-DD strings (e.g., "2023-06-15").
Internally, dates are stored as *time.Time in UTC with day-level precision. The sameDates() function compares only year, month, and day — ignoring time of day.
The sameDates(source, target) function determines if dates need syncing:
sameDates(nil, nil) = true // no dates, nothing to do
sameDates(nil, set) = true // don't clear existing target date
sameDates(set, nil) = false // need to sync date to target
sameDates(same, same) = true // already in sync
sameDates(diff, diff) = false // need to update target
Date comparison is integrated into SameProgressWithTarget() for both Anime and Manga, so date differences trigger sync updates automatically.
- Partial dates: AniList may return dates with only year/month set (day=nil). The
convertFuzzyDateToTimeOrNowfunction returns nil if any component is missing. - Timezone: All dates are stored in UTC. Day-level comparison ignores time of day.
- First sync: Entries with date differences will be updated on the first run after enabling date sync.