[comp.windows.ms.programmer] tzset and Windows

altman@sbcs.sunysb.edu (Jeff Altman) (03/27/91)

tzset() is a function which reads an environment variable
TZ and constructs from it three variables daylight, timezone,
and tzname which are used by the gmtime and localtime functions
for determining GMT from the set system time.

Has anyone been able to get this to work with Windows?

If not can anyone explain why it doesn't work?

Here is my test program: (please ignore the extra variables
I stole this header from a FreeWare project I am working on.)

Thanks in advance.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <windows.h>

long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
				LPSTR lpszCmdParam, int nCmdShow)
	{
	static char szAppName[] = "TZSET TEST" ;
	HWND        hwnd ;
	MSG         msg ;
	WNDCLASS    wndclass ;

	if (!hPrevInstance)
		{
		wndclass.style			= CS_HREDRAW | CS_VREDRAW ;
		wndclass.lpfnWndProc   	= WndProc ;
		wndclass.cbClsExtra		= 0 ;
		wndclass.cbWndExtra		= 0 ;
		wndclass.hInstance		= hInstance ;
		wndclass.hIcon			= NULL ;
		wndclass.hCursor		= LoadCursor (NULL, IDC_ARROW) ;
		wndclass.hbrBackground	= GetStockObject (BLACK_BRUSH) ;
		wndclass.lpszMenuName    = NULL ;
		wndclass.lpszClassName   = szAppName ;

		RegisterClass (&wndclass) ;
		}

	hwnd = CreateWindow (szAppName, 	// windows class name
			"TZSET TEST",		// window caption
			WS_OVERLAPPEDWINDOW | 	// window style
			WS_VSCROLL |
			WS_HSCROLL,
			CW_USEDEFAULT,			// initial x postion
			CW_USEDEFAULT,			// initial y postion
			CW_USEDEFAULT,			// initial x size
			CW_USEDEFAULT,			// initial y size
			NULL,				// parent window handle
			NULL, 				// window menu handle
			hInstance,			// program instance handle
			NULL) ;				// creation parameters
	ghwnd = hwnd ;

	/* Start a once per second timer for screen updates */
	while (!SetTimer (hwnd, 1, 1000, NULL))
		{
		MessageBox (hwnd,
			"Too many clocks or timers!",
			szAppName,
			MB_ICONEXCLAMATION | MB_OK) ;
		return FALSE ;
		}

	ShowWindow (hwnd, nCmdShow) ;
	UpdateWindow (hwnd) ;

	while (GetMessage (&msg, NULL, 0, 0))
		{
		TranslateMessage (&msg) ;
		DispatchMessage (&msg) ;
		}

	return msg.wParam ;
	}

long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
	{
	HDC			hdc ;
	PAINTSTRUCT	ps ;
	RECT 		rect ;
	static short   cxChar, cxCaps, cyChar, cxClient, cyClient, nMaxWidth,
				nHscrollPos, nVscrollPos, nHscrollMax, nVscrollMax ;
	TEXTMETRIC     tm ;
	HANDLE		hMem ;
	short          i, x, y, nPaintBeg, nPaintEnd, nVscrollInc, nHscrollInc ;

	time_t t;
	char tbuf[80];
	int yy, mm, dd, hh, mmm, ss ;
	static struct tm *area, *gmt;

	switch (message)
		{
		case WM_CREATE :
			putenv("TZ=EST5EDT") ;
			tzset() ;  /* Set the Time Zone                       */
			/* Optional TZ variable in the Environment */
			/* defaul is "EST5EDT"                    */

			hdc = GetDC(hwnd) ;

			GetTextMetrics (hdc, &tm) ;
			cxChar = tm.tmAveCharWidth ;
			cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
			cyChar = tm.tmHeight + tm.tmExternalLeading ;

			ReleaseDC (hwnd, hdc) ;

			return 0 ;

		case WM_PAINT :
			hdc = BeginPaint (hwnd, &ps) ;

			t = time (NULL);
			area = localtime(&t);
			sprintf (tbuf,"Local time is: %s", asctime(area)) ;
			TextOut (hdc, cxChar, cyChar, tbuf, lstrlen(tbuf)) ;
			gmt = gmtime(&t);
			sprintf ("GMT is:        %s", asctime(gmt));
			TextOut (hdc, cxChar, 2 * cyChar, tbuf, lstrlen(tbuf)) ;

			EndPaint (hwnd, &ps) ;
			return 0 ;

		case WM_TIMER :
			InvalidateRect(hwnd, NULL, TRUE) ;
			UpdateWindow(hwnd) ;
			return 0 ;

		case WM_DESTROY :
			KillTimer(hwnd, 1) ;
			PostQuitMessage (0) ;
			return 0 ;
		}

	return DefWindowProc (hwnd, message, wParam, lParam) ;
	}


--
- Jeff (jaltman@ccmail.sunysb.edu)

altman@sbpmt.cs.sunysb.edu (Jeff Altman) (03/28/91)

Well, it wasn't a windows problem.  Its a problem with
unclear documentation in Borland C++ (and probably every
other C Library reference manual.)

The problem is that gmtime and localtime both return 
pointers to structures that the manual refers to as
static structures that are re-written with each call.
What the manual does NOT say is that gmtime and localtime
both use the SAME static structure.

So:
	gmt = gmtime(&t) ;
	lt  = localtime(&t) ;
	printf (asctime(lt)) ;
	printf (asctime(gmt)) ;

both use the localtime value.


--
- Jeff (jaltman@ccmail.sunysb.edu)