Slide 1

Slide 1 text

「1⽇の睡眠」のはかり⽅ potatotips #92 iOS/Android開発Tips共有会 Takeshi Tanaka / RIZAP テクノロジーズ株式会社

Slide 2

Slide 2 text

© 2025 RIZAP TECHNOLOGIES,Inc. Tanaka Takeshi X: p0dee RIZAPテクノロジーズ株式会社 iOS/Android Engineer झຯ͸δϟζͱےτϨͰ͢ɻ

Slide 3

Slide 3 text

© 2025 RIZAP TECHNOLOGIES,Inc. アプリで⼊館から⽇々の健康管理まで、 すべてのことがアプリで可能! QRコードによる⼊退館 スターターキット (体組成計・ヘルスウォッチ) chocoZAP TV 「簡単」「便利」「楽しい」を コンセプトとしたコンビニジム ライザップが作ったコンビニジム ※QRコードは株式会社デンソーウェーブの登録商標です。

Slide 4

Slide 4 text

© 2025 RIZAP TECHNOLOGIES,Inc.

Slide 5

Slide 5 text

© 2025 RIZAP TECHNOLOGIES,Inc. .bodyMass .bodyMassIndex .leanBodyMass .bodyFatPercentage .heartRate .heartRateVariabilitySDNN .bloodPressureDiastolic .bloodPressureSystolic .bodyTemperature .activeEnergyBurned .basalEnergyBurned .sleepAnalysis

Slide 6

Slide 6 text

© 2025 RIZAP TECHNOLOGIES,Inc. .sleepAnalysis

Slide 7

Slide 7 text

© 2025 RIZAP TECHNOLOGIES,Inc. 睡眠時間 ⼊眠/起床時刻

Slide 8

Slide 8 text

© 2025 RIZAP TECHNOLOGIES,Inc. HKCategorySample startDate: 2025-07-16 00:53:31, endDate: 2025-07-16 01:05:31, category: asleepCore HKCategorySample startDate: 2025-07-16 01:05:31, endDate: 2025-07-16 01:20:01, category: asleepDeep HKCategorySample startDate: 2025-07-16 01:20:01, endDate: 2025-07-16 01:21:01, category: asleepCore HKCategorySample startDate: 2025-07-16 01:21:01, endDate: 2025-07-16 01:22:01, category: awake HKCategorySample startDate: 2025-07-16 01:22:01, endDate: 2025-07-16 01:44:01, category: asleepCore HKCategorySample startDate: 2025-07-16 01:44:01, endDate: 2025-07-16 01:47:01, category: asleepDeep HKCategorySample startDate: 2025-07-16 01:47:01, endDate: 2025-07-16 01:47:31, category: asleepCore HKCategorySample startDate: 2025-07-16 01:47:31, endDate: 2025-07-16 01:48:01, category: awake HKCategorySample startDate: 2025-07-16 01:48:01, endDate: 2025-07-16 01:54:01, category: asleepCore HKCategorySample startDate: 2025-07-16 01:54:01, endDate: 2025-07-16 02:19:01, category: asleepREM HKCategorySample startDate: 2025-07-16 02:19:01, endDate: 2025-07-16 02:29:01, category: asleepCore HKCategorySample startDate: 2025-07-16 02:29:01, endDate: 2025-07-16 02:44:01, category: asleepDeep HKCategorySample startDate: 2025-07-16 02:44:01, endDate: 2025-07-16 03:03:31, category: asleepCore HKCategorySample startDate: 2025-07-16 03:03:31, endDate: 2025-07-16 03:15:31, category: asleepDeep HKCategorySample startDate: 2025-07-16 03:15:31, endDate: 2025-07-16 03:24:31, category: asleepCore HKCategorySample startDate: 2025-07-16 03:24:31, endDate: 2025-07-16 03:27:31, category: asleepDeep HKCategorySample startDate: 2025-07-16 03:27:31, endDate: 2025-07-16 03:29:01, category: asleepCore HKCategorySample startDate: 2025-07-16 03:29:01, endDate: 2025-07-16 03:35:01, category: asleepDeep HKCategorySample startDate: 2025-07-16 03:35:01, endDate: 2025-07-16 03:41:01, category: asleepCore HKCategorySample startDate: 2025-07-16 03:41:01, endDate: 2025-07-16 03:48:31, category: asleepREM HKCategorySample startDate: 2025-07-16 03:48:31, endDate: 2025-07-16 03:50:01, category: awake HKCategorySample startDate: 2025-07-16 03:50:01, endDate: 2025-07-16 03:54:01, category: asleepCore HKCategorySample startDate: 2025-07-16 03:54:01, endDate: 2025-07-16 04:00:01, category: asleepREM HKCategorySample startDate: 2025-07-16 04:00:01, endDate: 2025-07-16 04:01:31, category: asleepCore HKCategorySample startDate: 2025-07-16 04:01:31, endDate: 2025-07-16 04:04:01, category: asleepREM HKCategorySample startDate: 2025-07-16 04:04:01, endDate: 2025-07-16 04:26:31, category: asleepCore HKCategorySample startDate: 2025-07-16 04:26:31, endDate: 2025-07-16 04:34:31, category: asleepDeep HKCategorySample startDate: 2025-07-16 04:34:31, endDate: 2025-07-16 04:35:01, category: asleepCore HKCategorySample startDate: 2025-07-16 04:35:01, endDate: 2025-07-16 04:36:31, category: awake HKCategorySample startDate: 2025-07-16 04:36:31, endDate: 2025-07-16 05:06:31, category: asleepCore HKCategorySample startDate: 2025-07-16 05:06:31, endDate: 2025-07-16 05:23:01, category: asleepREM HKCategorySample startDate: 2025-07-16 05:23:01, endDate: 2025-07-16 06:03:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:03:01, endDate: 2025-07-16 06:03:31, category: awake HKCategorySample startDate: 2025-07-16 06:03:31, endDate: 2025-07-16 06:17:31, category: asleepCore HKCategorySample startDate: 2025-07-16 06:17:31, endDate: 2025-07-16 06:32:01, category: asleepREM HKCategorySample startDate: 2025-07-16 06:32:01, endDate: 2025-07-16 06:33:31, category: awake HKCategorySample startDate: 2025-07-16 06:33:31, endDate: 2025-07-16 06:35:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:35:01, endDate: 2025-07-16 06:36:01, category: awake HKCategorySample startDate: 2025-07-16 06:36:01, endDate: 2025-07-16 06:38:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:38:01, endDate: 2025-07-16 06:40:01, category: awake HKCategorySample startDate: 2025-07-16 06:40:01, endDate: 2025-07-16 06:43:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:43:01, endDate: 2025-07-16 06:44:31, category: awake HKCategorySample startDate: 2025-07-16 06:44:31, endDate: 2025-07-16 06:49:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:49:01, endDate: 2025-07-16 06:51:01, category: awake HKCategorySample startDate: 2025-07-16 06:51:01, endDate: 2025-07-16 07:15:31, category: asleepCore

Slide 9

Slide 9 text

© 2025 RIZAP TECHNOLOGIES,Inc. HKCategorySample startDate: 2025-07-16 00:53:31, endDate: 2025-07-16 01:05:31, category: asleepCore HKCategorySample startDate: 2025-07-16 01:05:31, endDate: 2025-07-16 01:20:01, category: asleepDeep HKCategorySample startDate: 2025-07-16 01:20:01, endDate: 2025-07-16 01:21:01, category: asleepCore HKCategorySample startDate: 2025-07-16 01:21:01, endDate: 2025-07-16 01:22:01, category: awake HKCategorySample startDate: 2025-07-16 01:22:01, endDate: 2025-07-16 01:44:01, category: asleepCore HKCategorySample startDate: 2025-07-16 01:44:01, endDate: 2025-07-16 01:47:01, category: asleepDeep HKCategorySample startDate: 2025-07-16 01:47:01, endDate: 2025-07-16 01:47:31, category: asleepCore HKCategorySample startDate: 2025-07-16 01:47:31, endDate: 2025-07-16 01:48:01, category: awake HKCategorySample startDate: 2025-07-16 01:48:01, endDate: 2025-07-16 01:54:01, category: asleepCore HKCategorySample startDate: 2025-07-16 01:54:01, endDate: 2025-07-16 02:19:01, category: asleepREM HKCategorySample startDate: 2025-07-16 02:19:01, endDate: 2025-07-16 02:29:01, category: asleepCore HKCategorySample startDate: 2025-07-16 02:29:01, endDate: 2025-07-16 02:44:01, category: asleepDeep HKCategorySample startDate: 2025-07-16 02:44:01, endDate: 2025-07-16 03:03:31, category: asleepCore HKCategorySample startDate: 2025-07-16 03:03:31, endDate: 2025-07-16 03:15:31, category: asleepDeep HKCategorySample startDate: 2025-07-16 03:15:31, endDate: 2025-07-16 03:24:31, category: asleepCore HKCategorySample startDate: 2025-07-16 03:24:31, endDate: 2025-07-16 03:27:31, category: asleepDeep HKCategorySample startDate: 2025-07-16 03:27:31, endDate: 2025-07-16 03:29:01, category: asleepCore HKCategorySample startDate: 2025-07-16 03:29:01, endDate: 2025-07-16 03:35:01, category: asleepDeep HKCategorySample startDate: 2025-07-16 03:35:01, endDate: 2025-07-16 03:41:01, category: asleepCore HKCategorySample startDate: 2025-07-16 03:41:01, endDate: 2025-07-16 03:48:31, category: asleepREM HKCategorySample startDate: 2025-07-16 03:48:31, endDate: 2025-07-16 03:50:01, category: awake HKCategorySample startDate: 2025-07-16 03:50:01, endDate: 2025-07-16 03:54:01, category: asleepCore HKCategorySample startDate: 2025-07-16 03:54:01, endDate: 2025-07-16 04:00:01, category: asleepREM HKCategorySample startDate: 2025-07-16 04:00:01, endDate: 2025-07-16 04:01:31, category: asleepCore HKCategorySample startDate: 2025-07-16 04:01:31, endDate: 2025-07-16 04:04:01, category: asleepREM HKCategorySample startDate: 2025-07-16 04:04:01, endDate: 2025-07-16 04:26:31, category: asleepCore HKCategorySample startDate: 2025-07-16 04:26:31, endDate: 2025-07-16 04:34:31, category: asleepDeep HKCategorySample startDate: 2025-07-16 04:34:31, endDate: 2025-07-16 04:35:01, category: asleepCore HKCategorySample startDate: 2025-07-16 04:35:01, endDate: 2025-07-16 04:36:31, category: awake HKCategorySample startDate: 2025-07-16 04:36:31, endDate: 2025-07-16 05:06:31, category: asleepCore HKCategorySample startDate: 2025-07-16 05:06:31, endDate: 2025-07-16 05:23:01, category: asleepREM HKCategorySample startDate: 2025-07-16 05:23:01, endDate: 2025-07-16 06:03:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:03:01, endDate: 2025-07-16 06:03:31, category: awake HKCategorySample startDate: 2025-07-16 06:03:31, endDate: 2025-07-16 06:17:31, category: asleepCore HKCategorySample startDate: 2025-07-16 06:17:31, endDate: 2025-07-16 06:32:01, category: asleepREM HKCategorySample startDate: 2025-07-16 06:32:01, endDate: 2025-07-16 06:33:31, category: awake HKCategorySample startDate: 2025-07-16 06:33:31, endDate: 2025-07-16 06:35:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:35:01, endDate: 2025-07-16 06:36:01, category: awake HKCategorySample startDate: 2025-07-16 06:36:01, endDate: 2025-07-16 06:38:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:38:01, endDate: 2025-07-16 06:40:01, category: awake HKCategorySample startDate: 2025-07-16 06:40:01, endDate: 2025-07-16 06:43:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:43:01, endDate: 2025-07-16 06:44:31, category: awake HKCategorySample startDate: 2025-07-16 06:44:31, endDate: 2025-07-16 06:49:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:49:01, endDate: 2025-07-16 06:51:01, category: awake HKCategorySample startDate: 2025-07-16 06:51:01, endDate: 2025-07-16 07:15:31, category: asleepCore startDate: 2025-07-16 03:29:01, endDate: 2025-07-16 03:35:01, category: asleepDeep

Slide 10

Slide 10 text

© 2025 RIZAP TECHNOLOGIES,Inc.

Slide 11

Slide 11 text

© 2025 RIZAP TECHNOLOGIES,Inc.

Slide 12

Slide 12 text

© 2025 RIZAP TECHNOLOGIES,Inc.

Slide 13

Slide 13 text

© 2025 RIZAP TECHNOLOGIES,Inc. WWDC

Slide 14

Slide 14 text

© 2025 RIZAP TECHNOLOGIES,Inc. 昼寝

Slide 15

Slide 15 text

© 2025 RIZAP TECHNOLOGIES,Inc.

Slide 16

Slide 16 text

© 2025 RIZAP TECHNOLOGIES,Inc. 睡眠ログはさまざま ・⽇が変わる前/後に⼊眠するか ・⻑い中途覚醒 ・昼寝などの仮眠 ・データの取得元による差分 ・ログのばらつき

Slide 17

Slide 17 text

© 2025 RIZAP TECHNOLOGIES,Inc. HKCategorySample startDate: 2025-07-16 00:53:31, endDate: 2025-07-16 01:05:31, category: asleepCore HKCategorySample startDate: 2025-07-16 01:05:31, endDate: 2025-07-16 01:20:01, category: asleepDeep HKCategorySample startDate: 2025-07-16 01:20:01, endDate: 2025-07-16 01:21:01, category: asleepCore HKCategorySample startDate: 2025-07-16 01:21:01, endDate: 2025-07-16 01:22:01, category: awake HKCategorySample startDate: 2025-07-16 01:22:01, endDate: 2025-07-16 01:44:01, category: asleepCore HKCategorySample startDate: 2025-07-16 01:44:01, endDate: 2025-07-16 01:47:01, category: asleepDeep HKCategorySample startDate: 2025-07-16 01:47:01, endDate: 2025-07-16 01:47:31, category: asleepCore HKCategorySample startDate: 2025-07-16 01:47:31, endDate: 2025-07-16 01:48:01, category: awake HKCategorySample startDate: 2025-07-16 01:48:01, endDate: 2025-07-16 01:54:01, category: asleepCore HKCategorySample startDate: 2025-07-16 01:54:01, endDate: 2025-07-16 02:19:01, category: asleepREM HKCategorySample startDate: 2025-07-16 02:19:01, endDate: 2025-07-16 02:29:01, category: asleepCore HKCategorySample startDate: 2025-07-16 02:29:01, endDate: 2025-07-16 02:44:01, category: asleepDeep HKCategorySample startDate: 2025-07-16 02:44:01, endDate: 2025-07-16 03:03:31, category: asleepCore HKCategorySample startDate: 2025-07-16 03:03:31, endDate: 2025-07-16 03:15:31, category: asleepDeep HKCategorySample startDate: 2025-07-16 03:15:31, endDate: 2025-07-16 03:24:31, category: asleepCore HKCategorySample startDate: 2025-07-16 03:24:31, endDate: 2025-07-16 03:27:31, category: asleepDeep HKCategorySample startDate: 2025-07-16 03:27:31, endDate: 2025-07-16 03:29:01, category: asleepCore HKCategorySample startDate: 2025-07-16 03:29:01, endDate: 2025-07-16 03:35:01, category: asleepDeep HKCategorySample startDate: 2025-07-16 03:35:01, endDate: 2025-07-16 03:41:01, category: asleepCore HKCategorySample startDate: 2025-07-16 03:41:01, endDate: 2025-07-16 03:48:31, category: asleepREM HKCategorySample startDate: 2025-07-16 03:48:31, endDate: 2025-07-16 03:50:01, category: awake HKCategorySample startDate: 2025-07-16 03:50:01, endDate: 2025-07-16 03:54:01, category: asleepCore HKCategorySample startDate: 2025-07-16 03:54:01, endDate: 2025-07-16 04:00:01, category: asleepREM HKCategorySample startDate: 2025-07-16 04:00:01, endDate: 2025-07-16 04:01:31, category: asleepCore HKCategorySample startDate: 2025-07-16 04:01:31, endDate: 2025-07-16 04:04:01, category: asleepREM HKCategorySample startDate: 2025-07-16 04:04:01, endDate: 2025-07-16 04:26:31, category: asleepCore HKCategorySample startDate: 2025-07-16 04:26:31, endDate: 2025-07-16 04:34:31, category: asleepDeep HKCategorySample startDate: 2025-07-16 04:34:31, endDate: 2025-07-16 04:35:01, category: asleepCore HKCategorySample startDate: 2025-07-16 04:35:01, endDate: 2025-07-16 04:36:31, category: awake HKCategorySample startDate: 2025-07-16 04:36:31, endDate: 2025-07-16 05:06:31, category: asleepCore HKCategorySample startDate: 2025-07-16 05:06:31, endDate: 2025-07-16 05:23:01, category: asleepREM HKCategorySample startDate: 2025-07-16 05:23:01, endDate: 2025-07-16 06:03:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:03:01, endDate: 2025-07-16 06:03:31, category: awake HKCategorySample startDate: 2025-07-16 06:03:31, endDate: 2025-07-16 06:17:31, category: asleepCore HKCategorySample startDate: 2025-07-16 06:17:31, endDate: 2025-07-16 06:32:01, category: asleepREM HKCategorySample startDate: 2025-07-16 06:32:01, endDate: 2025-07-16 06:33:31, category: awake HKCategorySample startDate: 2025-07-16 06:33:31, endDate: 2025-07-16 06:35:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:35:01, endDate: 2025-07-16 06:36:01, category: awake HKCategorySample startDate: 2025-07-16 06:36:01, endDate: 2025-07-16 06:38:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:38:01, endDate: 2025-07-16 06:40:01, category: awake HKCategorySample startDate: 2025-07-16 06:40:01, endDate: 2025-07-16 06:43:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:43:01, endDate: 2025-07-16 06:44:31, category: awake HKCategorySample startDate: 2025-07-16 06:44:31, endDate: 2025-07-16 06:49:01, category: asleepCore HKCategorySample startDate: 2025-07-16 06:49:01, endDate: 2025-07-16 06:51:01, category: awake HKCategorySample startDate: 2025-07-16 06:51:01, endDate: 2025-07-16 07:15:31, category: asleepCore あらゆる睡眠パターンを網羅した計算アルゴリズムを考える必要がある

Slide 18

Slide 18 text

© 2025 RIZAP TECHNOLOGIES,Inc. 00 02 04 06 08 10 12 14 16 18 20 22 24 22 02

Slide 19

Slide 19 text

© 2025 RIZAP TECHNOLOGIES,Inc. 00 02 04 06 08 10 12 14 16 18 20 22 24 22 02

Slide 20

Slide 20 text

© 2025 RIZAP TECHNOLOGIES,Inc. 00 02 04 06 08 10 12 14 16 18 20 22 24 22 02

Slide 21

Slide 21 text

© 2025 RIZAP TECHNOLOGIES,Inc. 00 02 04 06 08 10 12 14 16 18 20 22 24 22 02

Slide 22

Slide 22 text

© 2025 RIZAP TECHNOLOGIES,Inc. 00 02 04 06 08 10 12 14 16 18 20 22 24 22 02 DIVOL DIVOL DIVOL

Slide 23

Slide 23 text

© 2025 RIZAP TECHNOLOGIES,Inc. 00 02 04 06 08 10 12 14 16 18 20 22 24 22 02 DIVOL DIVOL DIVOL

Slide 24

Slide 24 text

© 2025 RIZAP TECHNOLOGIES,Inc. 00 02 04 06 08 10 12 14 16 18 20 22 24 22 02 

Slide 25

Slide 25 text

© 2025 RIZAP TECHNOLOGIES,Inc. 00 02 04 06 08 10 12 14 16 18 20 22 24 22 02

Slide 26

Slide 26 text

// ひとつながりの睡眠をひとつの塊 chunk とするため、ログを chunk に分類する var chunks: [[HKCategorySample]] = [] var chunk: [HKCategorySample] = [samples[0]] for (i, sample) in samples.enumerated().dropFirst() { let before = samples[i - 1] let diff = abs(sample.startDate.timeIntervalSince1970 - before.endDate.timeIntervalSince1970) if diff < 60 * 10 { // 10分までの空きは許容してひと続きとみなす chunk.append(sample) } else { chunks.append(chunk) chunk = [sample] } } chunks.append(chunk)

Slide 27

Slide 27 text

// 時間が重複している chunk が⽣じることがあるため、組み合わせる(Asleep系とInBed系) // たとえば、 // Chunk1: 22:57-23:13 asleep // Chunk2: 22:57-00:49 in bed // Chunk3: 23:13-02:37 asleep // が存在したとき、⼊眠時刻は 22:57 としたいが、Chunk1は⽇を跨いでおらず、 // asleep かつ ⽇跨ぎの Chunk3 の 23:13 が⼊眠時刻となってしまう var targetChunks: [[HKCategorySample]] = [] for chunk in chunks { let chunkRange = chunk.first!.startDate ... chunk.last!.endDate let lastRange = last.first!.startDate ... last.last!.endDate if chunkRange.overlaps(lastRange) { let index = targetChunks.count - 1 targetChunks[index] = last + chunk } else { targetChunks.append(chunk) } }

Slide 28

Slide 28 text

var removeIndices: [Int] = [] for (i, chunk) in targetChunks.enumerated() { let periodRange = period.lowerBound ... period.upperBound let chunkRange = chunk.first!.startDate ... chunk.last!.endDate // 計測対象⽇(period)にかぶっている chunk 以外は除外する if !periodRange.overlaps(chunkRange) { removeIndices.append(i) } // chunk の期間が翌⽇の0:00を跨いでいる場合は除外する if chunkRange.contains(period.upperBound) { if !removeIndices.contains(i) { removeIndices.append(i) } } } targetChunks.remove(atOffsets: .init(removeIndices))

Slide 29

Slide 29 text

// 計測対象のログを集計 samples.forEach { sample in guard let category = HKCategoryValueSleepAnalysis(rawValue: sample.value) else { return } if sleepStart == nil, category.isKindOfAsleep { sleepStart = sample.startDate } if category.isKindOfAsleep { sleepEnd = sample.endDate } let duration = sample.endDate.timeIntervalSince(sample.startDate) switch category { case .inBed: inBed += duration case .asleepUnspecified: asleep += duration case .asleep: asleep += duration case .awake: awake += duration case .asleepCore: core += duration case .asleepDeep: deep += duration case .asleepREM: rem += duration @unknown default: return } }

Slide 30

Slide 30 text

© 2025 RIZAP TECHNOLOGIES,Inc. 健康には運動習慣と⼗分な睡眠が⼤切

Slide 31

Slide 31 text

© 2025 RIZAP TECHNOLOGIES,Inc. ありがとうございました︕