gpt4 book ai didi

c++ - 如何在C++中计算到下一个星期六的秒数?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:39:01 27 4
gpt4 key购买 nike

我正在尝试制作一个可以确定直到特定日期开始的秒数的计算器。

我目前能够确定当前的日期和时间,但是我不确定如何确定直到我想要的 future 一天开始的秒数(例如,星期六)。

我在想我可以计算出距周六还有多少天,然后将其转换为秒,但是问题是可能要增加额外的时间(我想知道午夜的时间,开始于一天)。

有人知道这怎么可能吗?

#pragma once
#include <string>
#include <ctime>

class DateTime
{
public:
DateTime();

DateTime(
const time_t& specific_datetime);

const std::string GetWeekDay() const;

const std::string GetMonth() const;

int GetDate() const;

const int GetSecondsUntilNextWeekDay(
const std::string& day_name) const;

private:

const int GetWeekDayNumberFromName(
const std::string& name) const;

tm m_time;
const time_t m_datetime;

DateTime(const DateTime &rhs);
DateTime &operator=(const DateTime &rhs);
};
#include "DateTime.h"

DateTime::DateTime() :
m_datetime(std::time(NULL))
{
localtime_s(&m_time, &m_datetime);
}

DateTime::DateTime(
const time_t& specific_datetime) :
m_datetime(specific_datetime)
{
localtime_s(&m_time, &m_datetime);
}

const std::string DateTime::GetWeekDay() const
{
switch (m_time.tm_wday)
{
case 0:
return "Sunday";
case 1:
return "Monday";
case 2:
return "Tuesday";
case 3:
return "Wednesday";
case 4:
return "Thursday";
case 5:
return "Friday";
case 6:
return "Saturday";
default:
return "Sunday";
}
}

const std::string DateTime::GetMonth() const
{
switch (m_time.tm_mon)
{
case 0:
return "January";
case 1:
return "February";
case 2:
return "March";
case 3:
return "April";
case 4:
return "May";
case 5:
return "June";
case 6:
return "July";
case 7:
return "August";
case 8:
return "September";
case 9:
return "October";
case 10:
return "November";
case 11:
return "December";
default:
return "January";
}
}

int DateTime::GetDate() const
{
return m_time.tm_mday;
}

int DateTime::GetYear() const
{
return 1900 + m_time.tm_year;
}

const int DateTime::GetSecondsUntilNextWeekDay(
const std::string& day_name) const
{
// Calculate how many seconds left for today...
const int todays_hours_left = 23 - m_time.tm_hour;
const int todays_minutes_left = (todays_hours_left * 60) + (59 - m_time.tm_min);
const int todays_seconds_left = (todays_minutes_left * 60) + (59 - m_time.tm_sec);
int overlap_seconds = 0;

// Calculate how many days until the desired date.
int current_day_number = m_time.tm_wday;
const int desired_day_number = GetWeekDayNumberFromName(day_name);

if (desired_day_number >= 0)
{
if (desired_day_number <= current_day_number)
{
// Find out how many days left in the week, add them to how many days until the today.
const int max_day = 6;
const int days_remaining = max_day - current_day_number;
overlap_seconds = (days_remaining * 24 * 60 * 60);
current_day_number = 0;
}

const int days_left = desired_day_number - current_day_number;
const int hours_left = days_left * 24;
const int minutes_left = hours_left * 60;
const int seconds_left = (minutes_left * 60) - (86400 - todays_seconds_left) + overlap_seconds;

return seconds_left;
}

return -1;
}

const int DateTime::GetWeekDayNumberFromName(
const std::string& name) const
{
if (name == "Sunday")
{
return 0;
}
else if (name == "Monday")
{
return 1;
}
else if (name == "Tuesday")
{
return 2;
}
else if (name == "Wednesday")
{
return 3;
}
else if (name == "Thursday")
{
return 4;
}
else if (name == "Friday")
{
return 5;
}
else if (name == "Saturday")
{
return 6;
}

return -1;
}
#include <iostream>

#include "DateTime.h"

int main()
{
DateTime date_time;

const int seconds = date_time.GetSecondsUntilNextWeekDay("Monday");
std::cout << "Seconds Till Date: " << seconds;
}

我希望,如果我想知道从当前时间(星期三晚上9:00)到星期四开始需要多长时间,它将返回3个小时或10800秒(可以工作)。

最佳答案

这个问题有两个微妙的问题:

  • 在特定时区是“一天的开始”吗?在UTC?

  • 通过阅读问题中的代码,看来“一天的开始”是由计算机的本地时区设置定义的。
  • 由于我们考虑了时区,因此我认为我们还需要考虑夏令时。例如,如果在特定日期的2:00进行1个小时的“ Spring 前进”转换,则该天从1:00到3:00的经过时间为1个小时,而在“正常”的日子为2个小时。除非我们打算计算“本地秒数”,而不是“物理秒数”。问题在这个问题上还不是很清楚...

  • 我使用“America / New_York”作为具有3个输入对的本地时区,测试了问题中给出的代码:
  • 星期六2019-03-02 22:02:05 EST到星期一2019-03-04 00:00:00 EST
  • 星期六2019-03-09 22:02:05 EST到星期一2019-03-11 00:00:00 EDT
  • 周六2019-03-16 22:02:05 EDT至星期一2019-03-18 00:00:00 EDT

  • 这是连续三周计算从星期六深夜到星期一开始之间的时间,中间三周由于夏令时生效而跨越了UTC偏移量变化。

    问题中的代码为所有输入对提供了7074s。采用hh:mm:ss格式,即01:57:54。与正确答案相距大约1天,对于第一对和第三对输入,答案是93475s,或者1天和7075s,或者1天和01:57:55。

    第二种情况的正确答案是,因为星期日只有23小时长,所以少了1小时,即89875秒。

    我没有跟踪问题中代码中的所有问题,但似乎至少存在以下3个问题:
  • 计算天数时出现的一个错误。
  • 计算秒数时出现的一个错误。
  • 忽略可能在本地时区发生的UTC偏移量更改。

  • Howard Hinnant's free, open-source, time zone library 1可用于纠正以下问题:
    #include "date/tz.h"
    #include <chrono>
    #include <iostream>

    std::chrono::seconds
    GetSecondsUntilNextWeekDay(date::weekday wd,
    date::sys_seconds tp =
    date::floor<std::chrono::seconds>(std::chrono::system_clock::now()))
    {
    using namespace std::chrono;
    using namespace date;
    auto zone = current_zone();
    zoned_seconds now = {zone, tp};
    auto today_local = floor<days>(now.get_local_time());
    weekday today_wd{today_local};
    auto delta_days = wd - today_wd;
    if (delta_days == days{0} && now.get_local_time() != today_local)
    delta_days += weeks{1};
    zoned_seconds target_date = {zone, today_local + delta_days};
    return target_date.get_sys_time() - now.get_sys_time();
    }

    int
    main()
    {
    using namespace date;
    using namespace std::chrono;
    zoned_seconds zt{current_zone(), local_days{March/9/2019} + 22h + 2min + 5s};
    std::cout << GetSecondsUntilNextWeekDay(Monday, zt.get_sys_time()) << '\n';
    }

    该代码通过为输入时间和目标时间(由当地时区定义的目标工作日的开始)创建一个 zoned_seconds来工作。 zoned_seconds是ozt_code的特殊化,具有秒精度。
    zoned_time<Duration>是本地时间点和 zoned_time的配对。可以等效地将其视为UTC时间点和 time_zone的配对。在任何一种情况下,都可以使用 time_zonelocal_time( sys_time是UTC)进行构造,并且可以提取 sys_timelocal_time两者,它们通过 sys_time相关。

    在此示例中, time_zonetime_zone一起找到,它可以检测计算机的当前本地时区设置。
    current_zone()是输入 now( sys_time是秒精度 sys_seconds的别名)和计算机当前本地时区的配对。
    sys_time是一种日精度 today_local,可通过获取 local_timenow并将其下限为日精度来找到。

    本地 local_time可以直接从 weekday构造。
    today_local是一个必须添加到 delta_days中才能达到 today_wd的目标 weekday的天数。 wd减法本质上是循环的:它总是导致[0,6]范围内的天数,并且独立于工作日的基础编码。例如,即使星期六编码为6,星期日编码为0,星期日也总是在星期六之后1天。

    如果当前 weekday与目标 weekday相同,并且这不是目标 weekday的第一秒,那么我们要计算到下周同一天的开始。否则, weekday是目标日期,此函数将返回0秒。

    给定天数( now)和当前日期( delta_days),可以使用 today_local计算目标日期。这是天精度的 today_local + delta_days,它将隐式转换为秒精度,并指向一天的开始。这与本地时区配对以构造 local_time

    现在我们有了 target_datetarget_date,我们只需要减去它们就可以得到所需的秒数。有两种方法可以执行此减法:
  • now中。这将以本地local_time定义的“日历秒”来度量时间。在此日历中,所有时间均为24小时。
  • time_zone中。这将在减法之前转换为UTC,从而测量“物理秒”。这将在上述情况2中检测到23h星期日。

  • 笔记:
  • 该代码不包含任何明确的转换常量,例如60、24或86400。
  • 该代码不会理会当前日期的经过秒数。
  • 该代码独立于sys_time编码,因此大大简化了。
  • 该代码完全避免使用过时的C计时API,因此可以大大简化。

  • 当我写这个:
    std::cout << GetSecondsUntilNextWeekDay(Saturday) << '\n';

    输出:
    128459s

    1 Howard Hinnant's time zone library现在是C++ 20规范的一部分,并做了一些细微的更改,例如将其放入 weekday中。

    关于c++ - 如何在C++中计算到下一个星期六的秒数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55623461/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com