C LANGUAGE TECHNOLOGY

【C言語】time関数で現在時刻の取得

2021年9月9日

悩んでいる人

C言語で現在時刻の取得方法を教えて!

こういった悩みにお答えします.

本記事の信頼性

  • リアルタイムシステムの研究歴12年.
  • 東大教員の時に,英語でOS(Linuxカーネル)の授業.
  • 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
  • プログラミング歴15年以上,習得している言語: C/C++PythonSolidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Assembler (x64,ARM).
  • 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」GitHubにオープンソースとして公開
  • 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
  • 最近は自然言語処理AIイーサリアムに関する有益な情報発信に従事.
    • (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
    • (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.

こういった私から学べます.

C言語を独学で習得することは難しいです.

私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.

私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!

友だち追加

独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!

time関数

time関数とは,現在時刻を秒単位で返す関数です.

返す値は,紀元(Epoch; 1970-01-01 00:00:00()UTC))からの秒数です.

もし引数tlocがNULLでない場合,返り値はtlocが挿すアドレスにも格納されます.

time_t型は,主にlong型(64ビット)をtypedefで定義される型です.

time関数を利用するコードは以下になります.

実行結果は以下になります.

1631144670と表示されましたが,現在時刻がいつなのかよくわからないですね...

そこで,time関数の派生関数を利用すると時刻をユーザにわかりやすく表示できるので,それぞれ紹介していきます.

ctime関数

ctime関数は,time_t型のカレンダー時刻timepを引数にとります.

ctime関数の返り値は,静的に確保された文字列へのポインタとなります.

返り値の文字列の最後に改行が挿入されています.

ctime関数の返り値は,日付・時刻関数のいずれかが呼び出されると上書きされる可能性があることに注意して下さい.

ctime関数を利用するコードは以下になります.

実行結果は以下になります.

1631145196の現在時刻が,2021年9月9日(木)の午前8時53分16秒だとわかります.

asctime/localtime/gmtime関数

asctime/localtime/gmtime関数は,ctime関数と同様に時刻に関連する関数です.

asctime関数は,引数tmをctime関数と同じ形式の文字列に変換します.

localtime関数は,カレンダー時刻timepをユーザが指定したタイムゾーン(実行環境のタイムゾーン)での時刻要素別の表現に変換します.

gmtime関数は,カレンダー時刻timepを協定世界時(UTC)での要素別の時刻へ変換します.

asctime関数の返り値は静的に割り当てられた文字列へのポインタ,localtime/gmtime関数の返り値は静的に確保された構造体です.

これらの関数の返り値は,日付・時刻関数のいずれかが呼び出されると上書きされる可能性があることに注意して下さい.

これらの関数で利用されるstruct tm構造体の定義は以下になります.

asctime/localtime/gmtime関数のコードは以下になります.

実行結果は以下になります.

ctime(&t)とasctime(localtime(&t))の結果が同じことがわかります.

また,asctime(gmtime(&t))の結果は 協定世界時(UTC)ですので,私の実行環境の日本標準時(UTC+9)の9時間前になっていることがわかります.

ctime/asctime/localtime/gmtime関数の返り値の上書き

ctime/asctime/localtime/gmtime関数の返り値が上書きされる可能性があることを説明しましたが,実際に上書きされるのか確認してみましょう.

説明を簡単にするため,ctime/localtime関数のみをピックアップして説明します.

ctime/localtime関数で返り値が上書きされることを確認するコードは以下になります.

まず,25~30行目でtime/ctime/localtime関数を呼び出して値を表示します.

32行目のsleep関数で1秒スリープします.

その後,34~41行目でtime/ctime/localtime関数を再度呼び出しています.

ここで,27,29行目に返り値を代入した変数sとtm,36,39行目に返り値を代入した変数s2とtm2は別物であることに注意して下さい.

つまり,s,tmは返り値を代入した後は更新していません.

実行結果は以下になります.

4行目のsの値と10行目のsの値が異なることがわかります.10行目のsの値は9行目のs2の値と同じく1秒後になっています.

print_tm関数の表示結果も同様です.

ctime_r/asctime_r/localtime_r/gmtime_r関数

ctime_r/asctime_r/localtime_r/gmtime_r関数は,第2引数のbuf/result(ユーザが確保したバッファや構造体)に結果を格納するリエントラント関数です.

※bufのサイズは26バイト以上が必要なことに注意して下さい.

これらの関数により,ctime/asctime/localtime/gmtime関数の返り値を上書きされないようにすることが可能になります.

結果として,デバッグしやすいコードを書くことができますので,基本的にはこれらの関数を利用しましょう.

ctime_r/asctime_r/localtime_r/gmtime_r関数を利用するコードは以下になります.

実行結果は以下になります.

mktime関数

mktime関数は,引数で指定したtmの(ローカルタイムで記述されている)要素別の時刻をカレンダー時刻に変換する関数です.

ここで,tm_wdayとtm_ydayで指定された値は無視されるので注意して下さい.

mktime関数を利用するコードは以下になります.

実行結果は以下になります.

strftime関数

strftime関数は,要素別の時刻tmの内容をformatで指定された書式指定子で変換し,長さmaxの文字列sに書き込む関数です.

例えば,RFC 2822準拠の日付形式は以下になります.

strftime関数を利用するコードは以下になります.

実行結果は以下になります.

dateコマンドでRFC 2822準拠のオプション(--rfc-2822)を設定した結果と同じになることがわかります.

廃止予定:gettimeofday/settimeofday関数

gettimeofday/settimeofday関数は,時刻を取得/設定する関数です.

struct timeval/struct timezone構造体の定義は以下になります.

※struct timezone構造体の利用は廃止予定とされています.

settimeofday関数を実行するためには,管理者権限が必要なことに注意して下さい.

POSIX.1-2008ではgettimeofday関数は廃止予定ですので(settimeofday関数もおそらく同様),代わりにclock_gettime/clock_settme関数の利用が推奨されています.

つまり,getimeofday/settimeofday関数は使わない方が良いですが,古いコードで利用されていることがありますので,簡単な使い方を紹介していきます.

gettimeofday関数を利用するコードは以下になります.

実行結果は以下になります.

正しく時刻を取得できていることがわかります.

settimeofday関数を利用するコードは以下になります.

14行目のgettimeofday関数で現在時刻を取得し,16行目で60 * 60秒(=3,600秒=60分=1時間)を足します.

18行目のsettimeofday関数で1時間後に時刻を設定します.

管理者権限なしでの実行結果は以下になります.

settimeofday.cの20行目のperror関数が呼び出されて,「settimeofday: Operation not permitted」が表示されていることがわかります.

管理者権限あり(sudoコマンドを利用)の実行結果は以下になります.

日付が1時間後に設定されていることがわかります.

この更新された日付はプログラム中では有効ですが,プログラムが終了した後は元の日付に戻ることに注意して下さい.

clock_gettime/clock_settime関数

clock_gettime/clock_settime関数は,指定されたクロックの時間を取得/設定する関数で,gettimeofday/settimeofday関数の代わりとして推奨されています.

時刻を取得/設定する場合は,clk_idにCLOCK_REALTIMEを設定します.

struct timespec構造体の定義は以下になります.

struct timespec構造体とstruct timeval構造体との違いは,ナノ秒を管理するtv_nsecとマイクロ秒を管理するtv_usecをそれぞれ持つことです.

clock_gettime関数を利用するコードは以下になります.

実行結果は以下になります.

gettimeofday関数の場合と同様です.

clock_settime関数を利用するコードは以下になります.

管理者権限なしでの実行結果は以下になります.

settimeofday関数の場合と同様です.

管理者権限あり(sudoコマンドを利用)の実行結果は以下になります.

こちらも同様です.

まとめ

C言語のtime関数で現在時刻の取得方法を紹介しました.

time関数には様々な派生関数がありますので,使いこなせるようにしましょう.

プログラムの実行時間の計測方法を学びたいあなたは,こちらの記事を読みましょう.

C言語を独学で習得することは難しいです.

私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.

私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!

友だち追加

独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!

-C LANGUAGE, TECHNOLOGY
-, , , , , , ,