DateTime型を.netを使わずに時刻情報に変換するには?

解決


APRIL  2012-04-05 11:18:22  No: 73295  IP: 192.*.*.*

環境:MFC VC++ 2005  .netなしです。

.netを使用したものから、System.DateTimeを使用して、以下のように時刻情報が64bitで渡されます。

DateTime time = ***; // UTCの情報
INT64 timeInfo = time.ToUniversalTime().Ticks;  // UTCの情報(64bit)


このtimeInfoを、.netなしのものから時刻情報に変換したいのですが、
どのようにすれば変換できますでしょうか?

編集 削除
tetrapod  2012-04-05 12:46:55  No: 73296  IP: 192.*.*.*

.net なし、というのがどういう意図なのかつかみかねるが・・・
同様「時刻情報」ってそれだけでは仕様がわからないが・・・

.NET Framework がインストールされていない XP や 2000 で動くよう、
.NET ランタイムライブラリは一切使用せず全部自前で書くのか、

.NET Framework の DLL は(一部分的に)使っていいが
原則はネイティブで書きたいのか、

前者だとしたらあまりお勧めできないかな・・・
.NET Framework のライブラリをきっちりつかっておけば、
今後変わりうるであろう「うるう秒の扱い」「各地域の暦法改正」とかに
Windows Update で自動的に対応できそうな気のせいがするが、
自作したらそういう「今後の変化」に自前で対応しないといけなくなる。

まあそれでも自作したいなら
http://msdn.microsoft.com/ja-jp/library/system.datetime(VS.80).aspx
に仕様はある。
うるう秒の扱いとか、グレゴリオ暦正式採択以前をどう扱うかとか、
いろいろ書いてないけど・・・

編集 削除
APRIL  2012-04-05 13:06:40  No: 73297  IP: 192.*.*.*

.netベースのアプリケーションがDateTimeを使用して出した値を、
MFCベース(.netなし)のアプリケーションがそれを使用して時刻情報に変換し出力したいです。
地道に計算するしかないのでしょうか?

編集 削除
仲澤@失業者  2012-04-05 13:19:38  No: 73298  IP: 192.*.*.*

>地道に計算するしかないのでしょうか?
何を計算したいかによりますね。

.NET も所詮はC、C++言語で書かれているわけですから、
受け渡しの仕様さえはっきりさせれば何の問題もないですよね。
「INT64 timeInfo」なるものがC言語の「__time64_t」と同じ
ものであれば、まさに何もすべきことはないわけですね。

編集 削除
tetrapod  2012-04-05 14:14:57  No: 73299  IP: 192.*.*.*

同一マシン上で .net ベースのソフトと非 .net ソフトが動いていて
.net ソフトの出力を 非 .net のソフトに食わせているなら
.net の DLL は使えるわけで C++/CLI あたりで DLL 作って変換するだけ

.net ベースのソフトが別マシンで動いていて
ネットワークとかファイルを経由して、非 .net ベースのソフトに入力され
その非 .net ベースのソフトのマシンに .NET Framework が入っていない
のであれば、ちまちま自作せざるを得ないだろう

後は「どう変換したいのか」次第ということで。

編集 削除
YuO  2012-04-05 14:23:42  No: 73300  IP: 192.*.*.*

FILETIMEでよければ,カウント単位が100nsですから,基点の時間をずらせば処理できそうです。
System::DateTime::Ticksは0001/01/01T00:00:00が基点,
FILETIMEは1601/01/01T00:00:00が基点です。

http://msdn.microsoft.com/ja-jp/library/system.datetime.ticks.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx

ざっと計算させたところ,504911232000000000を差し引いてFILETIMEを構築すればよさそうです。
// Console.WriteLine(new DateTime(1601, 1, 1, 0, 0, 0).Ticks);

あとはFileTimeToSystemTimeで各要素に分離できますから,それを元に処理するなりstruct tmを経由してtime_tにするなりすればよいと思います。
# MFCなのでWin32 APIの利用可として考えています。

編集 削除
APRIL  2012-04-12 17:47:32  No: 73301  IP: 192.*.*.*

結局うまく行きませんでしたので、C++/CLIを使ってtime_tを取得することにしました。  みなさま、ありがとうございました。

編集 削除
YuO  2012-04-12 18:06:02  No: 73302  IP: 192.*.*.*

うまくいかない,というのは何がうまくいかないのでしょう。
私が示した方法を使って変換できましたが。

// in C++/CLI (System::DateTimeとSystem::Consoleを使っているため)
#include <Windows.h>
#include <time.h>
#include <stdio.h>

using namespace System;

int main()
{
    DateTime dt = DateTime::Now;

    long long ftbase = dt.Ticks - 504911232000000000LL;

    // FILETIMEの構築
    FILETIME ft;
    ft.dwLowDateTime = static_cast<DWORD>(ftbase & 0xFFFFFFFFULL);
    ft.dwHighDateTime = static_cast<DWORD>((ftbase & 0xFFFFFFFF00000000ULL) >> 32);

    // FILETIME→SYSTEMTIME
    SYSTEMTIME st;
    FileTimeToSystemTime(&ft, &st);

    // SYSTEMTIME→struct tm
    struct tm tm;
    tm.tm_year = st.wYear - 1900;
    tm.tm_mon = st.wMonth - 1;
    tm.tm_mday = st.wDay;
    tm.tm_hour = st.wHour;
    tm.tm_min = st.wMinute;
    tm.tm_sec = st.wSecond;

    // struct tm→time_t
    time_t tt = mktime(&tm);

    Console::WriteLine(dt);
    Console::WriteLine("{0:D4}/{1:D2}/{2:D2} {3:D2}:{4:D2}:{5:D2}", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
    printf("%s", asctime(&tm));
    printf("%s", ctime(&tt));

    return 0;
}

編集 削除