C# 操作Fitbit数据导出文件 C#如何解析用户的健康和活动数据

8次阅读

fitbit导出文件是utf-8无bom编码的非标准csv,需用csvhelper按rfc 4180解析;字段含逗号、换行、嵌套引号,首行为带空格中文标题;须显式映射列名、处理跨日睡眠、用log id去重,并统一sleep type大小写。

C# 操作Fitbit数据导出文件 C#如何解析用户的健康和活动数据

Fitbit导出文件是什么格式?直接用StreamReader读会出错

Fitbit导出的ZIP包里全是CSV,但不是标准CSV:字段含逗号、换行、引号嵌套,且首行是带空格的中文标题(如"date","Calories Out"),部分字段值本身带双引号和换行符。用File.ReadAllLines()或手动Split(',')必乱码或解析错行。

  • 必须用支持RFC 4180的CSV解析器,.NET原生不带,推荐CsvHelper(NuGet安装CsvHelper
  • 别用Encoding.default——导出文件是UTF-8无BOM,windows默认ANSI会崩掉中文日期和活动名
  • 解压ZIP不能只取顶层文件:健康数据在export-*.zip/activities/sleep/等子目录,需递归遍历

CsvHelper怎么映射Fitbit的CSV字段?字段名大小写和空格要对齐

Fitbit CSV列名带空格、大小写混用(如"Activity Calories")、甚至有括号("Steps (Total)"),CsvHelper默认按属性名匹配会失败。必须显式配置映射,不能依赖自动推断。

  • 定义POCO类时,属性名用PascalCase,但加[Name("Activity Calories")]特性一一对应
  • 日期字段全是"MM/dd/yyyy HH:mm"格式,需注册DateTimeConverter并指定"M/d/yyyy H:mm"(注意单M单d,Fitbit不用前导零)
  • 数值字段如"Distance (mi)"可能为空字符串或”-“,需自定义TypeConverter返回0.0NULL
var config = new CsvConfiguration(CultureInfo.InvariantCulture) {     Delimiter = ",",     HasHeaderRecord = true,     Encoding = Encoding.UTF8 }; config.TypeConverterOptionsCache.GetOptions<DateTime>().Formats = new[] { "M/d/yyyy H:mm" };

解析睡眠数据时"Sleep Start Time""Sleep End Time"为什么拼不出完整DateTime?

Fitbit导出的睡眠CSV里,"Sleep Start Time""Sleep End Time"是纯时间(如"22:30"),而"Date"是日期(如"10/5/2023")。两者不在同一字段,也不能简单拼接——跨日睡眠(如23:45→7:20)会导致End时间早于Start。

  • 必须先解析DateDateTime.Date,再解析两个时间字段为TimeSpan
  • EndTime ,说明End属于次日,需给<code>Date.AddDays(1)
  • 别忽略"Duration (ms)"字段——它比计算差值更可靠,尤其当用户手动编辑过睡眠记录

导出文件里有重复记录或时间重叠,C#怎么去重又不丢数据?

Fitbit Web导出有时会把同一天的多次活动拆成多行,也可能因同步延迟产生毫秒级时间重叠;但真实活动不可能完全重复(比如两行都是“Walking”且开始/结束时间一致)。不能简单按StartTime + ActivityName去重。

  • 优先用"Log ID"字段(如果存在)——这是Fitbit服务端唯一标识,比时间戳更可信
  • 若无Log ID(如旧版导出),按Date + ActivityName + Duration (ms)三者组合哈希去重
  • 警惕“合并活动”:Fitbit App里手动合并的跑步记录,在CSV中仍保留原始多行,此时应保留Duration (ms)最大的那行,而非最早的时间戳

实际处理时,最麻烦的是睡眠数据里的“nap”和“main sleep”混在同一CSV里,但"Sleep Type"字段值不统一(有时是"Nap",有时是"nap",甚至空),得先.Trim().ToLowerInvariant()再判断——这个细节90%的人第一次都会漏。

text=ZqhQzanResources