mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 21:10:59 +00:00
fix(import): honour the energy unit an archived workout carries
`totalEnergyBurned` rides the same account-display-unit contract as the distance beside it: a Health app set to kilojoules writes `kJ`, and the column is kilocalories. Convert it through the shared table. Refs #944
This commit is contained in:
1 parent
bdfff04975
commit
e031e2211c
2 files changed
+44
-2
No files matched your search
@@ -1297,6 +1297,38 @@ describe("streamParseExportXml — the record's own unit (issue #944)", () => {
|
||||
expect(prisma._measurements[0].value).toBeCloseTo(2484, 6);
|
||||
});
|
||||
|
||||
it("stores a kilojoule workout burn in kilocalories", async () => {
|
||||
const tmp = mkdtempSync(join(tmpdir(), "healthlog-parser-energy-test-"));
|
||||
const xmlPath = join(tmp, "export.xml");
|
||||
writeFileSync(
|
||||
xmlPath,
|
||||
`<?xml version="1.0" encoding="UTF-8"?>
|
||||
<HealthData locale="en_AU">
|
||||
<Workout workoutActivityType="HKWorkoutActivityTypeRunning"
|
||||
duration="42.0"
|
||||
durationUnit="min"
|
||||
totalDistance="6.5"
|
||||
totalDistanceUnit="km"
|
||||
totalEnergyBurned="1724"
|
||||
totalEnergyBurnedUnit="kJ"
|
||||
startDate="2026-05-14 18:00:00 +0200"
|
||||
endDate="2026-05-14 18:42:00 +0200"
|
||||
sourceName="Apple Watch"/>
|
||||
</HealthData>`,
|
||||
);
|
||||
const prisma = makeFakePrisma();
|
||||
await streamParseExportXml({
|
||||
xmlPath,
|
||||
userId: "user-energy",
|
||||
userTimezone: "Europe/Berlin",
|
||||
prisma: prisma as unknown as PrismaClient,
|
||||
});
|
||||
|
||||
expect(prisma._workouts).toHaveLength(1);
|
||||
expect(prisma._workouts[0].totalDistanceM).toBeCloseTo(6500, 6);
|
||||
expect(prisma._workouts[0].totalEnergyKcal).toBeCloseTo(412.0458891, 6);
|
||||
});
|
||||
|
||||
it("stores a mile-scale walking distance in metres", async () => {
|
||||
const { prisma } = await importCumulativeFixture(
|
||||
cumulativeExportXml(
|
||||
|
||||
@@ -42,7 +42,10 @@ import {
|
||||
} from "@/lib/measurements/drain-per-sample-cumulative";
|
||||
import { reconcileExternalMeasurement } from "@/lib/measurements/reconcile-external-measurement";
|
||||
import { resolveHkWorkoutSportType } from "@/lib/measurements/hk-workout-activity-type-map";
|
||||
import { hkDistanceToMetres } from "@/lib/measurements/hk-units";
|
||||
import {
|
||||
convertHkValue,
|
||||
hkDistanceToMetres,
|
||||
} from "@/lib/measurements/hk-units";
|
||||
import { emitInsertedMeasurementArrivals } from "@/lib/arrivals/measurement-emit";
|
||||
import { maybeEnqueueMorningRefresh } from "@/lib/daily/morning-refresh-trigger";
|
||||
import { emitDataArrival } from "@/lib/arrivals/emit-shared";
|
||||
@@ -948,6 +951,7 @@ export async function streamParseExportXml(
|
||||
const totalDistance = Number.parseFloat(attrs.totalDistance ?? "");
|
||||
const totalEnergy = Number.parseFloat(attrs.totalEnergyBurned ?? "");
|
||||
const distanceUnit = attrs.totalDistanceUnit ?? "";
|
||||
const energyUnit = attrs.totalEnergyBurnedUnit ?? "";
|
||||
// Apple ships the ACCOUNT's own length unit on HKWorkout.totalDistance
|
||||
// (km for a metric account, mi for an imperial one); metres is the
|
||||
// canonical DB unit. issue #944 — the same conversion the `<Record>`
|
||||
@@ -969,7 +973,13 @@ export async function streamParseExportXml(
|
||||
startedAt: startDate,
|
||||
endedAt: endDate,
|
||||
durationSec,
|
||||
totalEnergyKcal: Number.isFinite(totalEnergy) ? totalEnergy : null,
|
||||
totalEnergyKcal: Number.isFinite(totalEnergy)
|
||||
? // issue #944 — the energy attribute carries the account's own
|
||||
// unit too: a Health app set to kilojoules writes `kJ` here, and
|
||||
// the column is kilocalories. Same shared conversion; an unknown
|
||||
// unit leaves the number alone.
|
||||
(convertHkValue(totalEnergy, energyUnit, "kcal") ?? totalEnergy)
|
||||
: null,
|
||||
totalDistanceM: distanceM,
|
||||
externalId,
|
||||
externalSourceVersion: attrs.sourceVersion ?? null,
|
||||
|
||||
Reference in new issue
Block a user