本文介绍了本地时间返回Windows开发GMT在Cygwin上运行的炮弹的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下code:

time_t t;
t = time( NULL );
elog << "timezone: " << getenv( "TZ" ) 
     << ", current local time: " << asctime( localtime( &t ));

如果我建立使用MSVC此code,和Windows DOS shell下运行它,我得到正确的本地时间:

If I build this code using MSVC, and run it under the windows DOS shell, I get the correct local time:

timezone: , current local time: Wed Jul 25 13:05:08 2012

但是,如果我喜欢的bash cygwin外壳下运行同一程序,这code返回GMT!

But if I run the same program under a cygwin shell like bash, this code returns GMT!

timezone: America/New_York, current local time: Wed Jul 25 18:05:08 2012

如果我运行这个程序在Linux或OSX,它也返回正确的本地时间。

If I run this program in Linux or OsX, it also returns the correct local time.

为什么?

@Update:现在是一年后,我发现我在下面给出的答案并不总是工作

@Update: It is now a year later and I found that the answer I gave below does not always work.

看来,某些程序解封TZ并不总是工作。我不知道为什么。但是有一个繁琐的解决方法。基本上,你没有设置TZ之后,你必须检查本地时间确实不再返回GMT,但只有当你实际上不是在GMT时区,当你调用本地时间计算手动调整的time_t的()或MAKETIME()

It seems that for some programs unsetting TZ does not always work. I don't know why. But there is a cumbersome workaround. Basically, right after you unset TZ, you have to check that local time is indeed no longer returning GMT, but only if you aren't actually in the GMT time zone, and compute a manual adjustment to time_t's when you call localtime() or maketime()

u64 localTimeOffset = 0;

static void unsetTz()
{
   static bool unsetTZ = false;
   if ( !unsetTZ )
   {
      putenv( "TZ=" );
      unsetTZ = true;

      // unsetting TZ does not always work. So we have to check if it worked
      // and make a manual adjustment if it does not. For long running programs
      // that may span DST changes, this may cause the DST change to not take 
      // effect.
      s32 tzOffset = getTzOffset();

      if ( tzOffset )
      {
         static char timeBuf[48];
         char* s = &(timeBuf[0]);
         struct tm* timeInfoGMT;
         struct tm* timeInfoLocal;

         time_t zero = 86400;
         timeInfoGMT = gmtime( &zero );
         u32 GMTHour = timeInfoGMT->tm_hour;

         timeInfoLocal = localtime( &zero );
         u32 localHour = timeInfoLocal->tm_hour;

         if ( localHour == GMTHour )
         {
            // unsetting tz failed. So we have to make a manual adjustment
            localTimeOffset = tzOffset * 60 * 60;
         }
      }
   }
}

s32 getTzOffset()
{
   TIME_ZONE_INFORMATION tzInfo;
   GetTimeZoneInformation( &tzInfo );
   s32 tz = ( tzInfo.Bias / 60 );
   return tz;
}

本地时间电话:

  time_t t = getAtTimeFromSomewhere();
  t -= localTimeOffset;
  timeInfo = localtime( &t );

一个调用MAKETIME:

A call to maketime:

 struct tm timestr;
 makeATMFromAStringForExample( time, timestr );
 time_t timet = mktime( &timestr );
 timet += localTimeOffset;

好时光。

推荐答案

这我花了一些时间来弄清楚,而且我希望这将是有用的人。

This took me some time to figure out, and I'm hoping it will be useful to others.

POSIX功能将使用环境变量 TZ 来确定要使用的时区。如果 TZ 没有设置将使用系统的默认时区。

POSIX functions like localtime will use the environment variable TZ to determine what timezone to use. If TZ is not set it will use the system's default timezone.

如果我在Linux或OS X上运行,正确设置 TZ 和一切正常。如果我在Windows上的shell中运行这个程序, TZ 没有设置,那么该函数返回操作系统的默认时区,而这又产生正确的结果。

If I run under Linux or OS X, TZ is set correctly and everything works. If I run this program in the shell on Windows, TZ is not set, so the function returns the operating system's default timezone, which again produces correct results.

如果我在Cygwin的shell中运行, TZ 设置 - 但因为我建立使用MSVC的程序,用MSVC自己STDC库 - 它不能跨preT Cygwin的 TZ 变量。因此,它默认为GMT

If I run in a Cygwin shell, TZ is set - but since I built the program using MSVC, using MSVC's own stdc library - it cannot interpret Cygwin's TZ variable. So it defaults to GMT.

有计划建成与海湾合作委员会在Cygwin下我敢打赌,它会在Cygwin的炮弹正常工作。

Had the program been built with GCC under Cygwin I bet it would work correctly in Cygwin shells.

因此​​,答案是要确保在调用POSIX时间功能,如本地时间程​​序(),如果你想时间函数向右下你有Cygwin的炮弹工作未设置 TZ

So the answer is to make sure in programs that call POSIX time functions like localtime(), if you want the time functions to work right under Cygwin shells you have to unset TZ.

我做到了,像这样:

void getLocalTime()
{
   #ifdef WIN32
   static bool unsetTZ = false;
   if ( !unsetTZ )
   {
      putenv( "TZ=" );
      unsetTZ = true;
   }
   #endif // !WIN32

   time_t t;
   t = time( NULL );
   elog << "timezone: " << getenv( "TZ" ) 
        << ", current local time: " << asctime( localtime( &t ));
}

这篇关于本地时间返回Windows开发GMT在Cygwin上运行的炮弹的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-26 22:36