/*
* TclGUID.h v1.1 2-26-2005 Scott Nichols
*
* This software is provided "AS IS", without a warranty of any kind.
* You are free to use/modify this code but leave this header intact.
*
*/
/* TCL Function prototype declarations */
#ifndef TclGUID_H
#define TclGUID_H
#define USE_NON_CONST
#define TCL_USE_STUBS
#include <tcl.h>
#include "StdAfx.h"
#include <afxdisp.h>
extern "C" {
__declspec(dllexport) int Tclguid_Init(Tcl_Interp* interp);
}
static int GetGUID_ObjCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int GetDate_ObjCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
#endifBegin Main Windows DLL Code/*
* TclGUID.cpp, v1.1 2/26/2005,
* Authored by Scott J. Nichols
*
* This software is provided "AS IS", without a warranty of any kind.
* You are free to use/modify this code but leave this header intact.
*/
#include "TclGUID.h"
static int
GetGUID_ObjCmd(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
GUID guid;
// create random GUID
guid = GUID_NULL;
::CoCreateGuid(&guid);
if (guid == GUID_NULL) {
Tcl_Obj *obj_result = Tcl_NewStringObj((const char *)"Unable to create GUID", -1);
Tcl_SetObjResult(interp, obj_result);
return TCL_ERROR;
}
BYTE * str;
UuidToString((UUID*)&guid, &str);
Tcl_UtfToUpper((char *)str);
// Return the GUID to the Tcl Interpreter
Tcl_Obj *obj_result = Tcl_NewStringObj((const char *)str, -1);
Tcl_SetObjResult(interp, obj_result);
RpcStringFree(&str);
return TCL_OK;
}
static int
GetDate_ObjCmd(
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
if (objc < 2) {
Tcl_WrongNumArgs(interp,1,objv, "value");
return TCL_ERROR;
}
double f;
Tcl_GetDoubleFromObj(interp,objv[1],&f);
COleDateTime d = COleDateTime::COleDateTime(f);
int M = d.GetMonth();
int D = d.GetDay();
int Y = d.GetYear();
int h = d.GetHour();
int m = d.GetMinute();
int s = d.GetSecond();
char date[20];
sprintf(date,"%i/%i/%i %i:%i:%i",M,D,Y,h,m,s);
// Return the date value to the Tcl Interpreter
Tcl_Obj *obj_result = Tcl_NewStringObj((const char *)date, -1);
Tcl_SetObjResult(interp, obj_result);
return TCL_OK;
}
/* Main Routine in the TCL Extension DLL */
int
Tclguid_Init(
Tcl_Interp *interp)
{
#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 1
// Does the TCL interpreter support version 8.3 of TCL?
if (Tcl_InitStubs(interp,"8.3",0) == NULL)
return TCL_ERROR;
#endif
Tcl_CreateObjCommand(interp, "GetGUID", GetGUID_ObjCmd,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateObjCommand(interp, "GetDate", GetDate_ObjCmd,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
return (Tcl_PkgProvide(interp,"TclGUID","1.0") == TCL_ERROR ? TCL_ERROR : TCL_OK);
}Begin Sample Tcl Call Codepackage require TclGUID clock format [clock scan [GetDate 38409.7202431]]Returns:
Sat Feb 26 5:17:09 PM Central Standard Time 2005
RS has taken this breakfast challenge to do some thinking :) The Unix "era" date is 1 Jan 1970, while OLE/COM's is 30 Dec 1899 - 25569 days earlier. Both seem to take a fixed day length of 86400 seconds, which ignores the problem of leap seconds, but anyway. The following code passes Scott's test:
proc fdate f {expr {round(($f-25569)*86400)}}and in the other direction, Unix time to OLE/COM time: proc date2fdate time {expr {$time/86400.+25569}}Testing:% clock format [fdate 38409.7202431] -gmt 1 Sat Feb 26 17:17:09 GMT 2005
snichols RS, your Tcl conversion code works great! Yours is much simpler than having to convert the value from a C/C++ Tcl extension. I'm going to use your Tcl code instead. Thank you.
male - 2007-08-17: I ran into the same problem, where a NC control returns DATE values over its COM interface. And I needed to use them as clock values. The result is ...
% set date 39280.84648148148 % clock format [fdate $date] Tue Jul 17 22:18:56 +0200 2007 % clock format [clock scan now] Fri Aug 17 21:15:58 +0200 2007But ... perhabs the NC control has a wrong adjusted time.

