C 文字列操作 新しいページはコチラ

提供: yonewiki
移動: 案内, 検索
(文字列と日付・日時・時間の変換)
(文字列と日付・日時・時間の変換)
4,577行: 4,577行:
  
 
これが時間処理の全般になると思います。この暦時間と非暦時間の特殊ケースとして1秒よりも小さい時間であるミリ秒の存在があるといったところでしょうか?そして、文字列として時間を表現する場合には国際社会を含めたルールに基づいて出力します。まずは標準時間からの差が最も重要な概念になります。日本なら+9時間です。あまり日本では関係の無い概念ですがサマータイムという表現もあります。グローバルな展開をするプログラムなら重要な概念かもしれません。相手の時間を思いやる必要のある双方向通信アプリとかなら、なおさら重要です。そして、曜日、午前、午後、24時間表現、表現習慣も国、地域、組織、個人によって異なります。ここでは、日付処理は別の場で考えるとして、システム時間から得られた時刻を文字列にする方法、網羅はできないですが、時刻文字列をシステム時間変数に設定し、歴時間変数として扱う方法について確認したいと思います。この日付の表現に関しても、文字コード変換でお世話になったICUはかなり手広くサポートしています。国際的な文字の変換処理に関する部分の処理系を強くしていっている印象です。たしかに個人では抱えきれないほど国際的な表現は複雑ですので、特化した組織があるというのは、ありがたいことです。
 
これが時間処理の全般になると思います。この暦時間と非暦時間の特殊ケースとして1秒よりも小さい時間であるミリ秒の存在があるといったところでしょうか?そして、文字列として時間を表現する場合には国際社会を含めたルールに基づいて出力します。まずは標準時間からの差が最も重要な概念になります。日本なら+9時間です。あまり日本では関係の無い概念ですがサマータイムという表現もあります。グローバルな展開をするプログラムなら重要な概念かもしれません。相手の時間を思いやる必要のある双方向通信アプリとかなら、なおさら重要です。そして、曜日、午前、午後、24時間表現、表現習慣も国、地域、組織、個人によって異なります。ここでは、日付処理は別の場で考えるとして、システム時間から得られた時刻を文字列にする方法、網羅はできないですが、時刻文字列をシステム時間変数に設定し、歴時間変数として扱う方法について確認したいと思います。この日付の表現に関しても、文字コード変換でお世話になったICUはかなり手広くサポートしています。国際的な文字の変換処理に関する部分の処理系を強くしていっている印象です。たしかに個人では抱えきれないほど国際的な表現は複雑ですので、特化した組織があるというのは、ありがたいことです。
 +
 +
<syntaxhighlight lang="cpp" line start="1">
 +
#pragma once
 +
#include "stdafx.h"
 +
#include <stdlib.h>
 +
#include <string> //std::string型定義
 +
#include <mbstring.h> //mbs***関数
 +
#include <iostream> //cpp cout etc 一般入出力関数
 +
#include <locale> //Locale関数
 +
#include <tchar.h> //TCHAR型+_tcs***関数
 +
#include "atlstr.h" //CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ
 +
#include "atlbase.h" //同上
 +
#include "cstringt.h" //CStringTの定義プリプロセッサ
 +
#include <vector>
 +
 +
 +
//_bstr_t型を利用するプリプロセッサ
 +
#include "comutil.h"
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "comsuppwd.lib")
 +
#else
 +
#pragma comment(lib, "comsuppw.lib")
 +
#endif
 +
//_bstr_t
 +
 +
//ICU ucnvプリプロセッサ
 +
#include <unicode/ucnv.h>
 +
#include <unicode/translit.h>
 +
#include <unicode/regex.h>
 +
#ifdef _DEBUG
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")//ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuucd.lib")//ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuiod.lib")
 +
#else
 +
#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")
 +
#pragma comment(lib, "icuuc.lib")
 +
#pragma comment(lib, "icuio.lib")
 +
#endif
 +
 +
 +
#include "UnicodeConverter.h"
 +
 +
 +
using namespace std;
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
    //_tsetlocale(LC_ALL, _T("Japanese")); ロケールセットすると_l関数でロケール指定しなくても日本語が使われます。
 +
 +
_locale_t localeJpanease;
 +
localeJpanease = _create_locale(LC_ALL, "Japanese");
 +
 +
//日付や時刻を取り込む文字列の長さは大きくないため、一時的な文字列確保はこのような固定長の配列で問題はないと思います。
 +
//それでも動的に文字列長を決定してメモリを確保したいというプログラムの効率を無視する場合には、自作しなければいけない関数が増えるのかと思います。
 +
char tmpbuf[128], timebuf[26], ampm[] = "AM";
 +
    time_t ltime;
 +
    struct _timeb structtimebTime;
 +
    struct tm today, gmt, xmas = { 0, 0, 12, 25, 11, 93 };//秒, 分, 時間, 日, 月(0~11), 年(1900年基準)
 +
    errno_t err;
 +
 +
 +
//__timeb64型構造体変数のアドレスを引数とする_ftime64_s関数でtstructに現在時刻を設定。
 +
_ftime_s( &structtimebTime ); // _ftimeはC4996
 +
    //
 +
 +
//環境変数TZに設定されたタイムゾーンにしたがってグローバル変数_daylight(夏時間設定)、
 +
//_timezone(秒時差)、_tzname配列(要素1->タイムゾーン名 要素2->夏時間タイムゾーン名)を設定。
 +
    _tzset();
 +
 +
 +
    //strtimeは10文字で現在時刻を引数の文字列変数に格納する関数。
 +
    _strtime_s( tmpbuf, 128 );
 +
    printf( "OS 時間:\t\t\t\t%s\n", tmpbuf );
 +
    //strdateは9文字で現在日付を引数の文字列変数に格納する関数。
 +
    _strdate_s( tmpbuf, 128 );
 +
    printf( "OS 日付:\t\t\t\t%s\n", tmpbuf );
 +
 +
    // Get UNIX-style time and display as number and string.
 +
    //time_t型変数のアドレスを引数とするtime関数でltimeに現在日時秒数を協定世界時UTCで設定。
 +
time( &ltime );
 +
    printf( "秒数による日時情報 1970年1月1日基準:\t%ld\n", ltime );
 +
   
 +
//ctime_sは第三引数のtime_t型UTC秒数情報から第一引数の文字列ポインタへ現在のシステムのタイムゾーン時刻生成する関数。
 +
err = ctime_s(timebuf, 26, &ltime);
 +
    if (err)
 +
    {
 +
      printf("ctime_s failed due to an invalid argument.");
 +
      exit(1);
 +
    }
 +
    printf( "現在日時情報 曜日月(英語):\t\t%s", timebuf );
 +
 +
 +
    //_gmtime64_s関数は第一引数のtm型構造体に第二引数で取得したUTC秒数情報からグリニッジ平均時Greenwich Mean Timeすなわち協定世界時を生成する関数。
 +
//※GMTが天体観測によって管理される時間で1秒の長さが微変動するもの、UTCは原子時計でGMTの情報をもとにうるう秒を入れたりして調整が入る。
 +
    err = _gmtime64_s( &gmt, &ltime );
 +
    if (err)
 +
    {
 +
      printf("_gmtime64_s failed due to an invalid argument.");
 +
    }
 +
//asctime_sは第三引数のtm型構造体に格納された情報から第一引数の文字列ポインタへ生成する関数。
 +
    err = asctime_s(timebuf, 26, &gmt);
 +
    if (err)
 +
    {
 +
      printf("asctime_s failed due to an invalid argument.");
 +
      exit(1);
 +
    }
 +
    printf( "協定世界時 UTC:\t\t\t\t%s", timebuf );
 +
 +
    //_localtime64_sはtime_t型UTC秒数情報から第一引数のtm型構造体に現在のタイムゾーンの時刻を設定する関数。
 +
    err = _localtime64_s( &today, &ltime );
 +
    if (err)
 +
    {
 +
      printf("_localtime64_s failed due to an invalid argument.");
 +
      exit(1);
 +
    }
 +
//tm構造体のtoday変数の24時間形式を格納するメンバ変数tm_hourの値が12以上なら午後なので、午前午後情報格納文字列の内容をPMに。
 +
    if( today.tm_hour >= 12 )
 +
    {
 +
        strcpy_s( ampm, sizeof(ampm), "PM" );
 +
        today.tm_hour -= 12;//午後で表現するので、12を引いた。但し、この後tm構造体変数として違う関数への引数とかにすると時間が12時間前になるので用途に注意。
 +
    }
 +
 +
    err = asctime_s(timebuf, 26, &today);
 +
    if (err)
 +
    {
 +
      printf("asctime_s failed due to an invalid argument.");
 +
      exit(1);
 +
    }
 +
 +
//timebufの12文字目から8文字が時間なので、その部分だけを出力し、ampmの情報を付加する。
 +
    printf( "12時間表記 時間:\t\t\t%.8s %s\n", timebuf + 11, ampm);
 +
 +
 +
    //_timeb64構造体に取得したタイムゾーン現在時刻のメンバ変数出力
 +
    printf( "現在時刻のミリ秒:\t\t\t%03u[ミリ秒]\n", structtimebTime.millitm );
 +
    printf( "協定世界時とタイムゾーン時刻の差:\t%d\n", structtimebTime.timezone / 60 );
 +
 +
size_t* pReturnValue = new size_t;
 +
int index = structtimebTime.dstflag;
 +
 +
//タイムゾーン名の文字列長をpReturnValueに取得
 +
_get_tzname(pReturnValue, NULL, 0, index);
 +
 +
char* timeZoneName = new char[*pReturnValue + 1];
 +
size_t sizeInBytes = *pReturnValue + 1;
 +
 +
//タイムゾーン名の取得
 +
_get_tzname(pReturnValue, timeZoneName, sizeInBytes, index);
 +
 +
printf( "タイムゾーン名:\t\t\t\t%s\n", timeZoneName );
 +
    printf( "タイムゾーン名文字数:\t\t\t%d[byte]\n", *pReturnValue );
 +
    printf( "夏時間適用フラグ:\t\t\t%s\n", structtimebTime.dstflag ? "夏時間" : "夏時間非適用" );
 +
 +
    //mktime関数は初期値が与えられているtm型構造体の情報から日時情報を生成し、他のメンバ変数の設定を行う関数
 +
    if(mktime(&xmas) != (time_t)-1)
 +
    {
 +
      err = asctime_s(timebuf, 26, &xmas);
 +
      if (err)
 +
      {
 +
          printf("asctime_s failed due to an invalid argument.");
 +
          exit(1);
 +
      }
 +
      printf( "指定日付\t\t\t\t%s\n", timebuf );
 +
    }
 +
 +
    err = _localtime64_s( &today, &ltime );
 +
    if (err)
 +
    {
 +
        printf(" _localtime64_s failed due to invalid arguments.");
 +
        exit(1);
 +
    }
 +
 +
    //★時間変数を文字列に変換する関数 strftime 
 +
    *pReturnValue = strftime( tmpbuf, 128, "Today is %A, day %d of %B in the year %Y.\n", &today );
 +
printf("%d[byte]\n",* pReturnValue);
 +
//英語表記の曜日、月名が取得できる。
 +
strftime( tmpbuf, 128, "Today is %A, day %d of %B in the year %Y.\n", &today );
 +
    printf( tmpbuf );
 +
 +
*pReturnValue = _strftime_l(tmpbuf, 128, "今日は(%y年)%Y年%B(%b月)%d日(%A:%a;%w番目の曜日 %W回目の%A) %U週目 %j日目 現在時刻は(%p %I)%H:%M:%S\n", &today, localeJpanease );
 +
printf("%d[byte]\n",* pReturnValue);
 +
//ロケール設定により日本語表記の曜日、月名が取得できる。
 +
_strftime_l(tmpbuf, 128, "今日は(%y年)%Y年%B(%b月)%d日(%A:%a;%w番目の曜日 %W回目の%A) %U週目 %j日目 現在時刻は(%p %I)%H:%M:%S\n", &today, localeJpanease );
 +
    printf( tmpbuf );
 +
 +
*pReturnValue = _strftime_l(tmpbuf, 128, "%#c,%#x,%%,%#S,%#a,%#%,%z,%Z\n", &today, localeJpanease );
 +
printf("%d[byte]\n",* pReturnValue);
 +
//ロケール設定により日本語表記の曜日、月名が取得できる。
 +
_strftime_l(tmpbuf, 128, "%#c,%#x,%%,%#S,%#a,%#%,%z,%Z\n", &today, localeJpanease );
 +
    printf( tmpbuf );
 +
  return 0;
 +
}
 +
</syntaxhighlight>
 +
出力結果
 +
<syntaxhighlight lang="text">
 +
OS 時間:                                20:18:03
 +
OS 日付:                                10/13/14
 +
秒数による日時情報 1970年1月1日基準:    1413199083
 +
現在日時情報 曜日月(英語):              Mon Oct 13 20:18:03 2014
 +
協定世界時 UTC:                        Mon Oct 13 11:18:03 2014
 +
12時間表記 時間:                        08:18:03 PM
 +
現在時刻のミリ秒:                      006[ミリ秒]
 +
協定世界時とタイムゾーン時刻の差:      -9
 +
タイムゾーン名:                        東京 (標準時)
 +
タイムゾーン名文字数:                  14[byte]
 +
夏時間適用フラグ:                      夏時間非適用
 +
指定日付                                Sat Dec 25 12:00:00 1993
 +
 +
53[byte]
 +
Today is Monday, day 13 of October in the year 2014.
 +
80[byte]
 +
今日は(14年)2014年10月(10月)13日(月曜日:月;1番目の曜日 41回目の月曜日) 41週目 286日目 現在時刻は(午後 08)20:18:03
 +
59[byte]
 +
2014年10月13日 20:18:03,2014年10月13日,,3,月,,東京 (標準時),東京 (標準時)
 +
</syntaxhighlight>
 +
と上記のように時間の表記を文字列に変換できます。ICUによる変換は時間があれば、サンプルを作成したいと思います。
 +
 
<!--
 
<!--
 
{|class="wikitable"
 
{|class="wikitable"

2014年10月13日 (月) 00:00時点における版



個人用ツール
名前空間

変種
操作
案内
ツールボックス