Raspberry Pi  > C > ローカルタイムのmsec(ミリ秒)まで取得して標準出力 > gettimeofday()使用版とclock_gettime()使用版

```
Raspberry Pi 2 Model B (以下RPi)
Raspbian Jessie
gcc (Raspbian 4.9.2-10) 4.9.2
```

### 概要

- ローカルタイムのmsecまでを取得して標準出力する

### 参考

- [C言語で正確にミリ秒マイクロ秒単位まで計測する方法](http://8ttyan.hatenablog.com/entry/2015/02/03/003428) by y8ttyan様
- [localtime](http://www9.plala.or.jp/sgwr-t/lib/localtime.html) by TOMOJI様
- [gettimeofday](https://linuxjm.osdn.jp/html/LDP_man-pages/man2/gettimeofday.2.html) @ linuxjm.osdn.jp
   
情報感謝です。

### 実装 (一部) > gettimeofday()使用

```RPi_i2c_comm_CLKSTR_180712.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
...
static void printTime(bool addLF)
{
	struct timeval tvToday; // for msec
	struct tm *ptm; // for date and time
	
	gettimeofday(&tvToday, NULL); // Today
	ptm = localtime(&tvToday.tv_sec);
	
	// date and time
	printf("%04d/%02d/%02d,%02d:%02d:%02d,",
		ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,
		ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    // msec
	printf("%03d,", (uint16_t)(tvToday.tv_usec / 1000));

	if (addLF) {
		printf("\n");
	}
}
```

### 実行例

```
$sudo ./RPi_i2c_comm_CLKSTR_180712
2018/08/01,11:03:17,700,C,767.066284,T,31.790649,RH,32.881165
2018/08/01,11:03:19,760,C,749.454285,T,31.817352,RH,33.106995
2018/08/01,11:03:21,803,C,760.685913,T,31.817352,RH,33.123779
2018/08/01,11:03:23,861,C,776.762817,T,31.804001,RH,33.029175
2018/08/01,11:03:25,920,C,782.709595,T,31.774628,RH,33.102417
```

上記のCの左側までがprintTime(false)での実装。

### 他環境の実装

- [c++ builder XE4, 10.2 Tokyo > TDateTime > ミリ秒 (msec) まで表示 > Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz")](https://qiita.com/7of9/items/a59f79b3c38ef3e178ed)
- [unity > System.DateTime > 現在のmsecを取得する実装](https://qiita.com/7of9/items/3e618c3bc8bdf790dcb4)
- [python > datetime > msecを取得する > msec = int(round(time.time() * 1000)) % 1000](https://qiita.com/7of9/items/9a47abf46f937cb543dc)


### メモ

確認しているセンサーは、2秒インターバルの動作が、実際には2秒50ミリ秒程度のインターバルになっている。
(DataReadyになってからの読込み時間も含む）。

### 教えていただいた事項
(追記 2018/08/01)

@tenmyo 様の[コメント](https://qiita.com/7of9/items/bf327b4327fcb5b08881/#comment-9cdeba7a0d1cb9281368)にてオーバーヘッドのこととclock_gettimeについて教えていただきました。

情報感謝です。

clock_gettimeに関して下記を見つけました。

- [clock_gettime() で高精度なタイムスタンプを取得して表示する](https://qiita.com/katoken-0215/items/3acb8b674c5e5bbbf9a4)
- [CLOCK_REALTIMEとCLOCK_MONOTONIC](https://qiita.com/ozaki-r/items/fb4a48c2833e4b479ae1)

### 実装 > clock_gettime()使用
(追記 2018/08/01)

clock_gettime()を使用してみました。

https://linuxjm.osdn.jp/html/LDP_man-pages/man2/clock_gettime.2.html
>CLOCK_REALTIME_COARSE (Linux 2.6.32 以降; Linux 特有)
高速だが精度が低い CLOCK_REALTIME。速度が非常に必要で、かつ高精度のタイムスタンプが不要な場合に使用するとよい。
... 
>CLOCK_MONOTONIC_COARSE (Linux 2.6.32 以降; Linux 特有)
>高速だが精度が低い CLOCK_MONOTONIC。速度が非常に必要で、かつ高精度のタイムスタンプが不要な場合に使用するとよい。


```printTime_180801.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <time.h>

static void printTime_clock_gettime(clockid_t clk_id, bool addLF)
{
    struct timespec tvToday; // for msec
    struct tm *ptm; // for date and time

    clock_gettime(clk_id, &tvToday);
    ptm = localtime(&tvToday.tv_sec);

    // date and time
    printf("%04d/%02d/%02d,%02d:%02d:%02d,",
        ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,
        ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    // msec
    printf("%03d,", (uint16_t)(tvToday.tv_nsec / 1000000));

    if (addLF) {
        printf("\n");
    }
}

int main(void)
{
	int loop;

	for(loop=0; loop<5; loop++) {
		printTime_clock_gettime(CLOCK_MONOTONIC_COARSE, /*addLF=*/true);
	}
	for(loop=0; loop<5; loop++) {
		printTime_clock_gettime(CLOCK_REALTIME_COARSE, /*addLF=*/true);
	}
}
```

```txt:run
$ gcc printTime_180801.c
$ ./a.out 
1970/01/01,15:37:29,515,
1970/01/01,15:37:29,525,
1970/01/01,15:37:29,525,
1970/01/01,15:37:29,525,
1970/01/01,15:37:29,525,
2018/08/01,16:59:39,362,
2018/08/01,16:59:39,362,
2018/08/01,16:59:39,362,
2018/08/01,16:59:39,362,
2018/08/01,16:59:39,362,
```

実時刻を得るにはCLOCK_REALTIME_XXXの方がを使うことになりそうですね。