当前位置: 首页 > 知识库问答 >
问题:

不使用本地时间的日光节约(DST)偏移量计算

滕夜洛
2023-03-14

我有下面的代码来计算偏移量,这里我在EST时区机器上执行下面的代码,其偏移量为-18000秒,即UTC-5.00

请注意,由于一些限制,我不能使用localtime(),这里要提到的限制很长。所以我用下面的逻辑从localtime epoch减去GMT epoch,如下所示,它完美地返回了偏移量。

现在,我想在这里假设DST(日光节约)的情况,偏移量为-14400秒,即UTC-4.00。由于EST时区DST(日光节约)的1次调整。

那么我下面提到的代码会起作用吗?以防系统有DST(日光节省)。我现在无法测试实时,因为DST(日光节省)在我的机器上不活动。

其计划如下:

/etc/localtime  Sun Mar 14 06:59:59 2021 UT = Sun Mar 14 01:59:59 2021 EST isdst=0 gmtoff=-18000
/etc/localtime  Sun Mar 14 07:00:00 2021 UT = Sun Mar 14 03:00:00 2021 EDT isdst=1 gmtoff=-14400
/etc/localtime  Sun Nov  7 05:59:59 2021 UT = Sun Nov  7 01:59:59 2021 EDT isdst=1 gmtoff=-14400
/etc/localtime  Sun Nov  7 06:00:00 2021 UT = Sun Nov  7 01:00:00 2021 EST isdst=0 gmtoff=-18000

所以想知道,当DST处于活动状态时,即2021年3月14日至2021年11月7日之间,我下面的代码会返回-14400的偏移量。time()函数是否考虑DST调整后的纪元时间。

#include <stdio.h>
#include <time.h>

int main ()
{
  time_t rawtime, g_epoch, l_epoch;
  struct tm * gtm, *ltm;
  signed long int offset;
  
  //Get current epoch time
  time ( &rawtime );
  
 // convert rawtime epoch to struct tm in GMT
  gtm = gmtime ( &rawtime );
// again convert back GMT struct tm to epoch
  g_epoch = mktime(gtm);

//convert rawtime epoch to "struct tm* ltm" in local time zone
  ltm= localtime(&rawtime);
// again convert back local time zone "struct tm* ltm" to epoch l_epoch
  l_epoch= mktime(ltm);
  

//calculate offset
  offset= l_epoch - g_epoch;
  
  printf("Rawtime: %u\n",rawtime);
 
  printf("GMTepoch: %u\n",g_epoch);

  printf("Local Epoch: %u\n",l_epoch);

  printf("Offset: %ld",offset);
  return 0;
}
O/p as below:
Rawtime: 1640176204
GMTepoch: 1640194204
Local Epoch: 1640176204
Offset: -18000

共有2个答案

凌黎明
2023-03-14

我认为这根本行不通,但我不确定。最好的情况是,它会在与DST之间的开关附近给出错误的结果。

如果您不能信任系统时区数据库,则始终可以使用您自己的tz数据库副本。Steve Summit指出,该数据库甚至附带了所有时区相关功能的参考实现,如localtime,因此无需自己解析数据库。

注意:数据库经常更新,因此如果需要在任意时区工作,则需要某种过程来频繁更新应用程序。

time()函数是否考虑DST调整后的纪元时间。

time返回自1970 UTC开始以来的秒数。

因此,结果不会改变你在世界上的位置。

Local time                  Time Zone Examples   time()
-------------------------   ------------------   ----------
2021-06-01T12:00:00Z        Etc/UTC, E./Dublin   1622548800
2021-06-01T08:00:00-04:00   "EDT", A./New_York   1622548800
2021-06-01T07:00:00-05:00   "EST", A./Bogota     1622548800

2021-06-01T12:00:00Z        Etc/UTC, E./Dublin   1622548800
2021-06-01T12:00:00-04:00   "EDT", A./New_York   1622563200
2021-06-01T12:00:00-05:00   "EST", A./Bogota     1622566800

那么我下面提到的代码会起作用吗?以防系统有DST(日光节省)。

mktime不是从localtime的相同位置获取有关本地时间的信息吗?那么为什么mktimelocaltime不工作的系统上工作呢?

但是我们可以说,mktime确实有效。

即使我们假设mktimelocaltime不起作用的系统上正常工作,我认为它也不会起作用。我想是gtm。tm_isdst将始终为零(因为gmtime使用的UTC没有DST),我认为这将导致下面的mktime返回与所需不同的内容。但这可以通过设置gtm来解决。tm_isdst-1

假设mktime确实返回了我们期望的结果。

即使mktime返回我们期望的结果,这种方法也是有缺陷的。它会在DST开关附近给出错误的偏移量。

// Current time zone:  America/New_York
// Current local time: 2022-03-12T22:30:00-05:00
// Change to DST:      In 3.5 hours.

// Get the current epoch time.
// This returns the same thing worldwide.
time(&rawtime);              // rawtime = 1647142200

// Convert current epoch time to UTC.
gtm = gmtime(&rawtime);      // gtm = 2021-03-13T03:30:00
gtm .tm_isdst = -1;

// Note that mktime expects a local time.
// But we're passing the current UTC time.
// So g_epoch is the epoch time for
// 2021-03-13T03:30:00 America/New_York
g_epoch = mktime(gtm);       // rawtime = 1647156600

这就是问题所在<代码>2021-03-13T03:30:00(本地)是在更改为DST之后,但我们只有2022-03-12T22:30:00(本地),这仍然是在更改为DST之前。这会给我们错误的补偿。

花玄裳
2023-03-14

通过对您的程序进行此小修改:

gtm = gmtime (&rawtime);
gtm->tm_isdst = -1;
g_epoch = mktime(gtm);

当DST生效时,它应该起作用。将tm_isdst设置为-1将强制mktime自行决定DST是否有效。

您还可以跳过涉及ltd ml_epoch的操作以及对localtime的调用。(我认为练习的全部目的是避免调用localtime?)你可以用

offset = rawtime - g_epoch;

但最终这仍然是一个相当可怕的黑客攻击,@ikegami指出,它在DST转换附近无法正常工作。例如,时间值1636261200正确地对应于2021 11月7日美国东部夏令时凌晨1点,但该代码将错误地确定它已经回落到东部夏令时。你所在的时区离格林威治标准时间越远,这个问题就越严重(将持续更长的时间)。也许有办法解决这个问题,但不会特别好。

 类似资料:
  • 问题内容: 只是为了验证这一点:我有这种la脚和脑死法,可以计算当前位置的时区偏移量。我想知道是否在需要调整“夏令时”时需要进行调整(目前,我所在的位置为CET时区,所以是“冬季时间”,因此很难验证)。 感谢您的任何提示。 问题答案: 通常,Joda时间会自己照顾DST,因此您不必担心。但是,我注意到您正在传递给getOffset()。鉴于时区偏移量取决于日期,因此您确实应该传递计算偏移量的日期/

  • 我想知道如何使用Moment. JS计算一天的小时数。原因是正常的一天是24小时。但是夏令时从Spring开始的那一天将是25小时。 或者我如何利用这个时刻。js甚至js来计算是否已达到Spring夏令时,记住DST在2a之后开始。M 我尝试使用的代码是 时刻([2017,2,12])。isDST(); 然而,我如何使用它,使它不仅能告诉我它的DST,而且还能检查它是否在凌晨2点以后。

  • 在Java 8 time API中,您可以创建一个LocalDateTime,该时间位于秋季DST时间变化期间(中欧时间)的时间重叠处。 您可以将其转换为ZonedDateTime,该时间表示使用ZoneId的精确时刻。 这样做实际上并不能解决歧义-仍然可能有两个时刻对应于此LocalDateTime和此区域(但偏移量不同)。 时间API如何以及为什么(欢迎参考)选择夏季偏移?

  • 问题内容: 我正在尝试获取特定时区的当前时间。我尝试了以下代码。 我得到的答案令人惊讶-16:57-错了1个小时tz.getRawOffset()-7000 3600000是-为什么亚利桑那州的夏令时是正确的?如何获得凤凰城或美国任何其他城市的正确挂钟时间? 问题答案: 亚利桑那州处于山区时区,但未遵守DST。如果您将时区指定为“ US / Mountain”,则计算机将应用Mountain时区中

  • 我需要确定是否在Linux(Redhat)中为给定的UTC偏移启用了日光节约。我得到了UTC 05:30之类的输入。我检查了zdump命令的用法。当与时区名称一起使用时,我们可以检查输出中isdst的值,以确定夏令时的状态。 zdump-v/usr/share/zoneinfo/Asia/Kolkata | grep 2013 如上所述,zdump需要区域名称。它不接受UTC偏移。 我还尝试了lo