fitbit-extract/source/app.d

59 lines
1.4 KiB
D
Raw Permalink Normal View History

import std.stdio;
import std.json;
import std.algorithm;
import std.array;
import std.csv;
import std.datetime;
import std.path;
import std.file;
import std.format;
int main(string[] args) {
if (args.length < 2) {
stderr.writeln("Missing required first argument for FitBit directory.");
return 1;
}
string fitbitDir = args[1];
auto w = parseWeight(fitbitDir);
writeln("Date, Weight");
foreach (e; w) {
writefln!"%s, %0.1f"(e.date.toISOExtString, e.weight);
}
return 0;
}
struct WeightEntry {
Date date;
float weight;
}
WeightEntry[] parseWeight(string fitbitDir) {
string exportDataDir = buildPath(fitbitDir, "Global Export Data");
Appender!(WeightEntry[]) app;
foreach (DirEntry entry; dirEntries(exportDataDir, SpanMode.shallow, false)) {
if (startsWith(baseName(entry.name), "weight")) {
JSONValue weightArray = parseJSON(cast(string) std.file.read(entry.name));
foreach (JSONValue weightObj; weightArray.array) {
WeightEntry w;
w.weight = weightObj.object["weight"].floating;
int day, month, year;
formattedRead!"%d/%d/%d"(weightObj.object["date"].str, month, day, year);
w.date = Date(year + 2000, month, day);
bool dateAlreadyExists = false;
foreach (WeightEntry existingEntry; app[]) {
if (existingEntry.date == w.date) {
dateAlreadyExists = true;
break;
}
}
if (!dateAlreadyExists) app ~= w;
}
}
}
return app[]
.sort!((a, b) => a.date < b.date)
.array;
}