Created
January 30, 2020 12:52
-
-
Save leoruhland/9a4e52b22dfae4e396eee00d9c86d7e7 to your computer and use it in GitHub Desktop.
Transform raw data from Toggl to a summarizing information grouping duration hours by task.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const csv = require('csv-parser'); | |
const fs = require('fs'); | |
const createCsvWriter = require('csv-writer').createObjectCsvWriter; | |
const csvWriter = createCsvWriter({ | |
path: 'out.csv', | |
header: [ | |
{ id: 'date', title: 'Date' }, | |
{ id: 'project', title: 'Project' }, | |
{ id: 'description', title: 'Description' }, | |
{ id: 'duration', title: 'Hours' }, | |
] | |
}); | |
const data = []; | |
const addTimes = (startTime, endTime) => { | |
var times = [0, 0, 0] | |
var max = times.length | |
var a = (startTime || '').split(':') | |
var b = (endTime || '').split(':') | |
// normalize time values | |
for (var i = 0; i < max; i++) { | |
a[i] = isNaN(parseInt(a[i])) ? 0 : parseInt(a[i]) | |
b[i] = isNaN(parseInt(b[i])) ? 0 : parseInt(b[i]) | |
} | |
// store time values | |
for (var i = 0; i < max; i++) { | |
times[i] = a[i] + b[i] | |
} | |
var hours = times[0] | |
var minutes = times[1] | |
var seconds = times[2] | |
if (seconds >= 60) { | |
var m = (seconds / 60) << 0 | |
minutes += m | |
seconds -= 60 * m | |
} | |
if (minutes >= 60) { | |
var h = (minutes / 60) << 0 | |
hours += h | |
minutes -= 60 * h | |
} | |
return ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2) + ':' + ('0' + seconds).slice(-2) | |
} | |
const csvRowExtract = (row) => { | |
data.push({ | |
project: row['Project'], | |
description: row['Description'], | |
date: row['Start date'], | |
duration: row['Duration'] | |
}); | |
}; | |
const csvReduce = (acc, each) => { | |
if (acc[each.project] === undefined) { | |
acc[each.project] = []; | |
} | |
if (acc[each.project][each.description] === undefined) { | |
acc[each.project][each.description] = []; | |
} | |
acc[each.project][each.description].push(each); | |
return acc; | |
} | |
const eachProject = (acc, each) => { | |
if (acc[each.project] === undefined) { | |
acc[each.project] = []; | |
} | |
if (acc[each.project][each.description] === undefined) { | |
acc[each.project][each.description] = []; | |
} | |
acc[each.project][each.description].push(each); | |
return acc; | |
} | |
fs.createReadStream('data.csv') | |
.pipe(csv()) | |
.on('data', csvRowExtract) | |
.on('end', () => { | |
console.log('CSV processed'); | |
const csvData = data.reduce(csvReduce, {}); | |
const projects = Object.keys(csvData); | |
const resultArray = projects.map(project => { | |
const projectData = csvData[project]; | |
const tasks = Object.keys(projectData); | |
return tasks.map(task => { | |
const taskData = projectData[task]; | |
const project = taskData[0].project; | |
const description = taskData[0].description; | |
const date = (taskData.length === 1) ? taskData[0].date : taskData[0].date + ' - ' + taskData[taskData.length - 1].date; | |
const duration = taskData.reduce((acc, each) => { | |
return addTimes(acc, each.duration); | |
}, '00:00:00'); | |
return { | |
date, | |
project, | |
description, | |
duration | |
} | |
}); | |
}); | |
const result = resultArray.reduce((acc, each) => { | |
each.map(e => { | |
acc.push(e); | |
}) | |
return acc; | |
}, []) | |
csvWriter | |
.writeRecords(result) | |
.then(() => console.log('CSV written')); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment