Skip to main content

DateTime Models

DateTime models provide standardized date, time, and duration representations used throughout DDEX messages for release dates, licensing periods, and temporal metadata.

Core Types

EventDate

Represents dates with varying precision levels:

interface EventDate {
date: string; // ISO 8601 format
precision?: DatePrecision;
isApproximate?: boolean;
territoryCode?: string; // Territory-specific dates
}

enum DatePrecision {
Year = 'Year',
Month = 'Month',
Day = 'Day',
Hour = 'Hour',
Minute = 'Minute',
Second = 'Second'
}

Duration

Represents time durations in ISO 8601 format:

interface Duration {
value: string; // e.g., "PT3M45S" for 3 minutes 45 seconds
}

Period

Represents time periods with start and end boundaries:

interface Period {
startDate?: EventDate | string;
endDate?: EventDate | string;
duration?: Duration;
isOpenEnded?: boolean;
}

Date Formats

ISO 8601 Format

All dates follow ISO 8601 standard:

// Full precision
"2024-03-15T14:30:00Z" // UTC with seconds
"2024-03-15T14:30:00-05:00" // With timezone offset

// Reduced precision
"2024-03-15" // Date only
"2024-03" // Month only
"2024" // Year only

Duration Format

Durations use ISO 8601 period notation:

"PT3M45S"      // 3 minutes 45 seconds
"PT1H30M" // 1 hour 30 minutes
"P1Y2M3DT4H5M6S" // 1 year, 2 months, 3 days, 4 hours, 5 minutes, 6 seconds

Common Use Cases

Release Dates

interface Release {
releaseDate: EventDate;
originalReleaseDate?: EventDate;
pLineDate?: EventDate;
cLineDate?: EventDate;
}

// Example release date
const releaseDate: EventDate = {
date: "2024-03-15",
precision: "Day",
isApproximate: false
};

Licensing Periods

interface Deal {
validityPeriod?: Period;
commercialModelType: CommercialModelType[];
}

// Example licensing period
const licensePeriod: Period = {
startDate: "2024-01-01T00:00:00Z",
endDate: "2025-12-31T23:59:59Z",
isOpenEnded: false
};

Content Duration

interface SoundRecording {
duration?: Duration;
technicalDetails?: {
duration?: Duration;
previewStartTime?: Duration;
previewDuration?: Duration;
};
}

// Example audio duration
const trackDuration: Duration = {
value: "PT3M45S" // 3:45
};

Usage Examples

Parsing Dates

const result = await parser.parse(xmlContent);

// Access release dates
const release = result.flat.releases[0];
console.log('Release date:', release.releaseDate.date);

// Check date precision
if (release.releaseDate.precision === 'Year') {
console.log('Year-only release date');
}

// Territory-specific dates
const usReleaseDate = release.releaseInformation
.find(info => info.territories?.some(t => t.code === 'US'))
?.salesStartDate;

Building Date Data

const buildRequest = {
releases: [{
releaseId: 'R123456789',
releaseDate: {
date: '2024-03-15',
precision: 'Day',
isApproximate: false
},
originalReleaseDate: {
date: '2023',
precision: 'Year',
isApproximate: true
},
releaseInformation: [{
territories: [{ code: 'US' }],
salesStartDate: '2024-03-15T00:00:00-05:00'
}]
}]
};

Working with Durations

// Parse duration string
function parseDuration(isoDuration: string): number {
// Convert "PT3M45S" to total seconds
const match = isoDuration.match(/PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?/);
if (!match) return 0;

const hours = parseInt(match[1] || '0', 10);
const minutes = parseInt(match[2] || '0', 10);
const seconds = parseInt(match[3] || '0', 10);

return hours * 3600 + minutes * 60 + seconds;
}

// Format duration from seconds
function formatDuration(totalSeconds: number): string {
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;

let duration = 'PT';
if (hours > 0) duration += `${hours}H`;
if (minutes > 0) duration += `${minutes}M`;
if (seconds > 0) duration += `${seconds}S`;

return duration;
}

// Usage
const track = result.flat.resources.soundRecordings[0];
const durationSeconds = parseDuration(track.duration?.value || 'PT0S');
console.log(`Track length: ${Math.floor(durationSeconds / 60)}:${(durationSeconds % 60).toString().padStart(2, '0')}`);

Period Calculations

function isPeriodActive(period: Period, date: Date = new Date()): boolean {
const now = date.toISOString();

// Check start date
if (period.startDate && now < period.startDate) {
return false;
}

// Check end date
if (period.endDate && !period.isOpenEnded && now > period.endDate) {
return false;
}

return true;
}

// Usage with deals
const activeDeal = result.flat.deals.find(deal =>
!deal.validityPeriod || isPeriodActive(deal.validityPeriod)
);

Timezone Handling

UTC vs Local Time

// Prefer UTC for international distribution
const utcDate = "2024-03-15T00:00:00Z";

// Local time with offset
const localDate = "2024-03-15T00:00:00-05:00"; // EST

// Date only (timezone-agnostic)
const dateOnly = "2024-03-15";

Territory-Specific Dates

Different territories may have different release dates:

const releaseInfo = [{
territories: [{ code: 'US' }],
salesStartDate: '2024-03-15T00:00:00-05:00' // EST
}, {
territories: [{ code: 'JP' }],
salesStartDate: '2024-03-16T00:00:00+09:00' // JST (next day)
}];

See Also