localtime doesn't use the configured timezone

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

localtime doesn't use the configured timezone

Post by Shine »

The code below demonstrates the problem, if you have confgured a different timezone for your PSP than UTC. "localtime" returns UTC instead of the local time.

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <time.h>

/* Define the module info section */
PSP_MODULE_INFO&#40;"TEST", 0, 1, 1&#41;;

/* Define the main thread's attribute value &#40;optional&#41; */
PSP_MAIN_THREAD_ATTR&#40;THREAD_ATTR_USER | THREAD_ATTR_VFPU&#41;;

int main&#40;void&#41;
&#123;
	pspDebugScreenInit&#40;&#41;;

	int c = 0;
	while &#40;1&#41; &#123;
		time_t t = time&#40;NULL&#41;;
		struct tm *stm = localtime&#40;&t&#41;;
		pspDebugScreenClear&#40;&#41;;
		pspDebugScreenPrintf&#40;"%02i&#58;%02i&#58;%02i", stm->tm_hour, stm->tm_min, stm->tm_sec&#41;;
		sceDisplayWaitVblankStart&#40;&#41;;
		sceDisplayWaitVblankStart&#40;&#41;;
		if &#40;c++ == 300&#41; break;
	&#125;
	sceKernelExitGame&#40;&#41;;

	return 0;
&#125;
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Re: localtime doesn't use the configured timezone

Post by jimparis »

Shine wrote:The code below demonstrates the problem, if you have confgured a different timezone for your PSP than UTC.
See if something like

Code: Select all

setenv&#40;"TZ","EST5EDT"&#41;;
before localtime helps.
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Re: localtime doesn't use the configured timezone

Post by Shine »

jimparis wrote:See if something like

Code: Select all

setenv&#40;"TZ","EST5EDT"&#41;;
before localtime helps.
This doesn't help, because I'm not living in the EST5 timezone :-)

But in general setting the TZ variable helps. With this function the timezone will be set to the PSP timezone:

Code: Select all

void initTimezone&#40;&#41;
&#123;
	int tzOffset = 0;
	sceUtilityGetSystemParamInt&#40;PSP_SYSTEMPARAM_ID_INT_TIMEZONE, &tzOffset&#41;;
	int tzOffsetAbs = tzOffset < 0 ? -tzOffset &#58; tzOffset;
	int hours = tzOffsetAbs / 60;
	int minutes = tzOffsetAbs - hours * 60;
	static char tz&#91;10&#93;;
	sprintf&#40;tz, "GMT%s%02i&#58;%02i", tzOffset < 0 ? "+" &#58; "-", hours, minutes&#41;;
	setenv&#40;"TZ", tz, 1&#41;;
	tzset&#40;&#41;;
&#125;
I don't know, where is the right position in newlib or PSPSDK, but I think it should be set by default in some startup code.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Re: localtime doesn't use the configured timezone

Post by jimparis »

Shine wrote:This doesn't help, because I'm not living in the EST5 timezone :-)
It was a proof of concept :P Thanks for the init code.

I just committed changes so that the timezone is initialized on startup. As a side-effect, newlib now requires linking with -lpsputility. This is handled automatically if you use build.mak or SDL.
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

I'm going to remove the dependencies in newlib libc on tzset(), setenv(), and libpsputility.a because they include a ton of bloated code in typical newlib fashion. I'm also not too fond of depending on -lpsputility for just one function, and then needing to specify -lpsputility for autoconf programs, etc.

To do this, I'm going to replace tzset() with a version that calls jimparis' original tz init code the first time it's called. This will mean that any programs that need the timezone set must explicitly call tzset(). Note that newlib setenv() will call tzset() when you pass "TZ", so it's best to just call tzset() directly.
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

Also, programs using tzset() will still be required to link against -lpsputility, but the rest of the world will not.
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

Done. Also, I was wrong about setenv(), it only calls tzset() if TZ was previously set. Anyway the code should be correct. It will also make sure TZ isn't set before initializing it from the PSP settings, so that programs can override TZ if necessary.

As an aside, removing this code and replacing printf() and its cousins with a smaller version (an earlier change), now makes newlib libc only slightly larger than PSPSDK's libc for most programs. The remaining differences in size can probably be attributed to the thread-safe code in newlib (which we don't use currently). Just wanted to point out that it's now feasible for *everyone* to use newlib :).
carlosedp
Posts: 21
Joined: Tue Jun 19, 2007 4:20 am
Location: Sao Paulo / Brazil

initTimezone() function improved with DST support.

Post by carlosedp »

I have improved the initTimezone function above with support for DST.

I have tested on FW 3.71.

Code: Select all

void initTimezone&#40;&#41; &#123;
   int tzOffset = 0;
   int dst = 0;
   sceUtilityGetSystemParamInt&#40;PSP_SYSTEMPARAM_ID_INT_TIMEZONE, &tzOffset&#41;;
   sceUtilityGetSystemParamInt&#40;PSP_SYSTEMPARAM_ID_INT_DAYLIGHTSAVINGS, &dst&#41;;
   int tzOffsetAbs = tzOffset < 0 ? -tzOffset &#58; tzOffset;
   int hours = tzOffsetAbs / 60;
   int minutes = tzOffsetAbs - hours * 60;
   char *tz;
   if &#40;dst == 1&#41; &#123;
      tz = malloc&#40;14*sizeof&#40;char&#41;&#41;;
      sprintf&#40;tz, "GMT%s%02i&#58;%02i DST", tzOffset < 0 ? "+" &#58; "-", hours, minutes&#41;;
   &#125; else &#123;
      tz = malloc&#40;10*sizeof&#40;char&#41;&#41;;
      sprintf&#40;tz, "GMT%s%02i&#58;%02i", tzOffset < 0 ? "+" &#58; "-", hours, minutes&#41;;
   &#125;
   
   setenv&#40;"TZ", tz, 1&#41;;
   tzset&#40;&#41;;
&#125;
Carlos
The Mindcaster
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

Thanks, if you can provide this as a patch against the pspdev repository I'll add it in.
Post Reply