Exporting and Importing all Timing Projects

Timing now offers a proper built-in sync solution, so in many cases that option is preferable. However, you can still use these scripts to export a "master set" of projects, then import those projects on all your teammates' Macs. For more information, see this article.

Simply copy one of the following script into a new "Script Editor" document, select "JavaScript" as the script's language, and press run (see this article for more detailed instructions).
After pasting them, consider saving the scripts to disk for future re-use. You could even save them to iCloud Drive (or e.g. Dropbox or Google Drive) to have them available on all your Macs.
Feel free to customize the scripts for your use cases.

Note: We do not take responsibility for any data loss incurred by running these scripts.
Make sure to back up your data (e.g. by copying the directories mentioned here to a different location) before running these scripts.

Exporting All Timing Projects to a JSON File

// Copyright (c) 2017 timingapp.com / Daniel Alm. All rights reserved.
// This script is licensed only to extend the functionality of Timing. Redistribution and any other uses are not allowed without prior permission from us.
var helper = Application("TimingHelper");
var app = Application.currentApplication();
app.includeStandardAdditions = true;

var projectHierarchyPath = app.chooseFileName({ withPrompt: "Select which file to write the Project hierarchy to.", defaultName: "TimingProjects.json" }).toString();

$.NSFileManager.defaultManager.createDirectoryAtPathWithIntermediateDirectoriesAttributesError($(projectHierarchyPath).stringByDeletingLastPathComponent.stringByStandardizingPath, true, $(), $());

function enumerateProjects(projects) {
	return projects.map(function(project) { return { name: project.name(), color: project.color(), productivityRating: project.productivityRating(), ruleData: project.ruleData(), children: enumerateProjects(project.projects()) }; });
}

var fullProjectHierarchy = enumerateProjects(helper.rootProjects());

var str = $(JSON.stringify(fullProjectHierarchy, null, 4));
str.writeToFileAtomicallyEncodingError($(projectHierarchyPath).stringByStandardizingPath, true, $.NSUTF8StringEncoding, $());

Importing a List of Projects from a JSON File into Timing

var importRules = true;
var overwriteExistingRules = true;

// Copyright (c) 2017 timingapp.com / Daniel Alm. All rights reserved.
// This script is licensed only to extend the functionality of Timing. Redistribution and any other uses are not allowed without prior permission from us.
var helper = Application("TimingHelper");
var app = Application.currentApplication();
app.includeStandardAdditions = true;

app.displayDialog("Before proceeding, please make sure to back up your Timing database.\n\nSee https://timingapp.com/help/faq#data on which folders you need to back up.");

var projectHierarchyPath = app.chooseFile({ withPrompt: "Select which file to read the Project hierarchy from.", ofType: ["public.json"] }).toString();

function importProjects(projects, parent) {
	var existingChildren = parent ? parent.projects() : helper.rootProjects()
	for (var project of projects) {
		if (!project.name) continue;
		
		var newProject = existingChildren.filter(function(childProject) { return childProject.name() == project.name; })[0];
		var args = { name: project.name };
		if (project.color) { args.color = project.color; }
		if (project.productivityRating) { args.productivityRating = project.productivityRating; }
		if (importRules
			&& project.ruleData
			&& (overwriteExistingRules || !newProject || !newProject.ruleData())) { args.ruleData = project.ruleData; }
		if (!newProject) {
			if (parent) {
				args.parentProject = parent;
			}
			newProject = helper.createProject(args);
		} else {
			helper.updateProject(newProject, args);
		}
		
		importProjects(project.children, newProject);
	}
}

var fullProjectHierarchy = $.NSString.stringWithContentsOfFileEncodingError(
               $(projectHierarchyPath).stringByStandardizingPath,
               $.NSUTF8StringEncoding,
               $()
          ).js;

importProjects(JSON.parse(fullProjectHierarchy), null);

Importing a List of Projects from a Text File into Timing

The following script imports a list of project names from a plain text file.
Each project should be on a separate line.
If you'd like to import projects hierarchically, use the project's full "path" in one line, separated by " ▸ ".
Example: Client A ▸ Project X ▸ Subproject Y

// Copyright (c) 2017 timingapp.com / Daniel Alm. All rights reserved.
// This script is licensed only to extend the functionality of Timing. Redistribution and any other uses are not allowed without prior permission from us.
var helper = Application("TimingHelper");
var app = Application.currentApplication();
app.includeStandardAdditions = true;

app.displayDialog("Before proceeding, please make sure to back up your Timing database.\n\nSee https://timingapp.com/help/faq#data on which folders you need to back up.");

function createProjectWithNameChainElements(projectNameChainElements) {
	var currentProject = null;
	var currentSearchSpace = helper.rootProjects();
	for (var projectName of projectNameChainElements) {
		if (!projectName) continue;
		
		var newProject = currentSearchSpace.filter(function(project) { return project.name() == projectName; })[0];
		if (!newProject) {
			var arguments = { name: projectName };
			if (currentProject) {
				arguments["parentProject"] = currentProject;
			}
			newProject = helper.createProject(arguments);
		}
		currentProject = newProject;
		currentSearchSpace = currentProject.projects();
	}
	return currentProject;
}

function createProjectWithNameChain(projectNameChain) {
	return createProjectWithNameChainElements(projectNameChain.split(" ▸ "));
}

var path = app.chooseFile({ withPrompt: "Select which file to read the project list from.", ofType: ["public.text"] });

var projectNameChains = $.NSString.stringWithContentsOfFileEncodingError(
               $(path.toString()).stringByStandardizingPath,
               $.NSUTF8StringEncoding,
               $()
          ).js.split("\n");

var helper = Application("TimingHelper");
for (var projectNameChain of projectNameChains) {
	if (projectNameChain) createProjectWithNameChain(projectNameChain);
}