Converting UNIX dates to a readable format on Mac

I tend to run into UNIX dates — large numbers representing points in time as seconds since the first second of 1970, something like 1500000000 for 2017-07-14 05:40:00 — all the time in my work, dealing with servers, web APIs, etc.

Here's how to make them readable on a Mac. All text below assumes macOS 10.13.

Terminal

The most straightforward solution is probably to open Terminal.app and run date:

# Outputs Fri Jul 14 05:40:00 EEST 2017
date -r 1500000000

# Outputs 2017-07-14 05:40:00
date -r 1500000000 +'%F %T'

Services: shell + AppleScript

Command line isn't your only option. macOS has a Services menu where you can add all sorts of useful things that operate on your selection:

Services menu screenshot

You can create a Service menu item pretty easily from the date invocation above.

  1. Launch Automator

  2. Create a new document. Select Service when Automator prompts for a type.

  3. Add "Run Shell Script" action. Select /bin/sh as the shell. Set the following as the content:

    xargs -I INPUT date -r INPUT +'%F %T'
    
  4. Add a "Run AppleScript" action. Set the following as the content:

on run {input, parameters} tell me to display dialog input with title "Date" buttons "OK" return input end run ``` 5. Save the document, select text anywhere, select the <Program Name> → Services → <Your Automator document name> menu item, and you'll get a dialog box with the converted date.

Services: Javascript

Starting a shell, invoking (with no input validation) a couple of command line tools, then piping that to AppleScript is not very satisfactory.

You might be able to eliminate the first step and do all of it in AppleScript. But that would mean writing more AppleScript. I prefer to avoid that.

macOS offers another option: JavaScript for Automation, also known as JXA. Not exactly the greatest of languages either, but it's not as read only as AppleScript. And while its standard library is not great, it can handle dates. So we can reduce our Automator script to one action and improve our input validation at the same time.

  1. Start by again creating a new service in Automator.

  2. Add a "Run JavaScript" action. Set the following as content:

    function run(input, parameters) {
    	const app = Application.currentApplication();
    	app.includeStandardAdditions = true;
    
    	const inputInt = parseInt(input);
    	if (isNaN(inputInt)) {
    		app.displayAlert("Not an integer: " + input);
    		return input;
    	}
    
    	const d = new Date(inputInt * 1000);
    
    	app.displayDialog(d.toISOString(), {
    		withTitle: "Date",
    		buttons: ["Close"],
    		defaultButton: "Close",
    	});
    
    	return input;
    }
    
  3. Now again save the document. The new service is available in the Services menu.

Here's the window you get:

Date dialog screenshot

The output from toISOString isn't quite as nice as %F %T from date, but if you're used to ISO dates, it's not bad. Making it prettier is left as an exercise to the reader. Start with Mozilla's documentation for Date.

There you have it! Maybe some day we can use Swift and the Foundation libraries for automation, but meanwhile I can live with the JS solution.

© Juri Pakaste 2024