BuiltOnAir

Find the Earliest Date Across Multiple Date Fields

Created by: Creator: Victoria Plummer

Dates Utility

When a record has multiple date fields, sometimes you’d like to know which date is the earliest.

In this example base, each record is a social post that has different live dates for different channels. I’d like to know the earliest live date across all three channels. I could do this in a formula, but the ‘LIVE DATE’ field is also used by other teams, so I’d rather calculate the date with the below script.

Script Code


							 // ?? ?Add all the date fields you need here ? ??
let fields = ['Instagram Date','IG Stories Date','Facebook Date','LIVE DATE']

// Let Airtable know which table and views records you want to use
let table = base.getTable("Content");
let view = table.getView('All');
let query = await view.selectRecordsAsync({fields:fields});
let records = query.records;

// Find the Earliest Date
let dates = records.map( c => fields.map( x => (c.getCellValue(x) != null && x != 'LIVE DATE') ? Date.parse(c.getCellValue(x)) : null).filter(x => x));
let minRaw = dates.map( c => c.reduce((acc,cur) => Math.min(acc,cur)));
let min = minRaw.map( c => new Date(c).toISOString())
let update = min.map( (c,i) => ({id:records[i].id,fields:{
    'LIVE DATE': c
}}));

/*
    Use this function to perform 'Update', 'Create', or 'Delete'
    async actions on batches of records that could potentially 
    more than 50 records.

    ::PARAMETERS::
    action = string; one of 3 values:
           - 'Update' to call table.updateRecordsAsync()
           - 'Create' to call table.createRecordsAsync()
           - 'Delete' to call table.deleteRecordsAsync()

    table = Table; the table the action will be performed in

    records = Array; the records to perform the action on
            - Ensure the record objects inside the array are
            formatted properly for the action you wish to
            perform

    ::RETURNS::
    recordsActedOn = integer, array of recordId's, or null; 
                   - Update Success: integer; the number of records processed by the function
                   - Delete Success: integer; the number of records processed by the function
                   - Create Success: array; the id strings of records created by the function
                   - Failure: null;
*/
async function batchAnd(action, table, records) {
    let recordsActedOn;

    switch (action) {
        case 'Update':
            recordsActedOn = records.length;
            while (records.length > 0) {
                await table.updateRecordsAsync(records.slice(0, 50));
                records = records.slice(50);
            };
            break;
        
        case 'Create':
            recordsActedOn = [];
            while (records.length > 0) {
                let recordIds = await table.createRecordsAsync(records.slice(0, 50));
                recordsActedOn.push(...recordIds)
                records = records.slice(50);
            };
            break;

        case 'Delete':
            recordsActedOn = records.length;
            while (records.length > 0) {
                await table.deleteRecordsAsync(records.slice(0, 50));
                records = records.slice(50);
            }
            break;

        default:
            output.markdown(`**Please use either 'Update', 'Create', or 'Delete' as the "action" parameter for the "batchAnd()" function.**`);
            recordsActedOn = null;
    }
    return recordsActedOn;
}


// Update the records
await batchAnd('Update',table,update)