我如何将一年中的某一天(1-365)转换为其等效日期(即2013年1月5日)C++

How can I convert the day of the year (1-365) to its equivalent date (ie. January 5th, 2013) C++

本文关键字:日期 C++ 5日 1月 2013年 转换 某一天 一年 1-365      更新时间:2023-10-16

我尝试过搜索一种可以实现这一点的算法,但没有找到任何结果。

我有构造函数Date2013(int dd)。

在这个成员函数中,我创建了一个包含月份的数组(一月、二月等)

然后我创建了一个if语句,它接收dd,如果dd在第1-31天之间,那么输出January,如果它在32-59天之间,然后输出二月。

我遇到的问题是,然后取他们输入的数字dd,并将其转换为一个月中合适的日期。一年中的第三十四天是二月二日。

有人知道任何算法吗,或者知道我可以实现这一点的方法吗?

(我刚刚开始学习我的C++,所以在任何代码中进行解释或注释都会非常有帮助,这样我就可以理解你的思维过程和语法)

最便携的&可靠的方法是使用ANSI C mktime&localtime函数,它将与C或C++一起工作

更新:

要回答如何实现自己的算法而不是使用标准的C库mktime函数的问题,一个好的起点是查看已知的工作代码,如glibc mktime源代码。您需要的相关花絮包括:

来自glibc 2.17(HEAD)mktime.c第141行附近:

#define TM_YEAR_BASE 1900
/* Return 1 if YEAR + TM_YEAR_BASE is a leap year.  */
static inline int
leapyear (int year)
{
  /* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
     Also, work even if YEAR is negative.  */
  return
    ((year & 3) == 0
     && (year % 100 != 0
         || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
}

从glibc 2.17(HEAD)mktime.c第160行开始:

const unsigned short int __mon_yday[2][13] =
{
    /* Normal years.  */
    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
    /* Leap years.  */
    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};

一个示例C++类实现了一个构造函数,该构造函数将year&dayOfYear到相应月份&dayOfMonth可能看起来像:

#include <iostream>
using namespace std;
#define MONTHS_IN_YEAR 12
class MyDateClass {
public:
MyDateClass(int year, int dayOfYear) {
    int yearOffset = dayOfYear - TM_YEAR_BASE;
    int leapYearIndex = leapyear(year) ? 1 : 0;
    int daysInYear = leapYearIndex ? 366 : 365;
    this->year = year;
    this->dayOfYear = dayOfYear;
    if (dayOfYear >= 1 && dayOfYear <= daysInYear) {
        for (int mon = 0; mon < MONTHS_IN_YEAR; mon++) {
           if (dayOfYear <= __mon_yday[leapYearIndex][mon+1]) {
               month = mon + 1;
               dayOfMonth = dayOfYear - __mon_yday[leapYearIndex][mon];
               break;
           }
        }
    } else {
        cerr << "day of year must be between 1 and " << daysInYear << endl;
        month = 0;
        dayOfMonth = 0;
    }
}
// Get month 1=January, 12=December       
inline int getMonth() { return month; }
// Get day of month
inline int getDayOfMonth() { return dayOfMonth; }
// Get year
inline int getYear() { return year; }
// Get day of yar
inline int getDayOfYear() { return dayOfYear; }
private:
   int month;
   int dayOfMonth;
   int year;
   int dayOfYear;
};

希望我不会因为展示可能完成任务的示例代码而被投票否决。当然,你可以随心所欲地实现它。这只是一个例子。


如果您更愿意使用现有的mktime功能(推荐),它很可能出现在您正在编程的任何平台上的标准C库中,我的原始回答内容如下

使用mktime时,您需要确保将tm_mon=0和tm_mday设置为一年中的某一天(有关更好的解释,请参阅mktime文档),但简而言之,mktime会忽略tm_wday和tm_yday,只翻译tm_mday,如果您也将tm_mon设置为0,则它本质上会将tm_mday解释为一年之日;

以下是一些说明这一点的工作示例代码,它们将在C或C++中工作:

#include <stdio.h>      /* printf, scanf */
#include <time.h>       /* time_t, struct tm, time, mktime */
#include <strings.h>    /* bzero */
int main () {
   time_t loctime;
   struct tm timeinfo, *loctimeinfo;
   int year, day;
   /* prompt user for year and day-of-the-year */
   printf ("Enter year: "); scanf ("%d",&year);
   printf ("Enter day of the year: "); scanf ("%d",&day);
   /* initialize timeinfo and modify it to the user's choice */
   bzero(&timeinfo, sizeof(struct tm));
   timeinfo.tm_isdst = -1;  /* Allow mktime to determine DST setting. */
   timeinfo.tm_mon   = 0;
   timeinfo.tm_mday = day;
   timeinfo.tm_year = year - 1900;
   loctime = mktime (&timeinfo);
   loctimeinfo = localtime(&loctime);
   printf ("The date for that day of the year is %s.n", asctime(loctimeinfo));
   return 0;
}

编译&示例运行:

$ g++ -o t2 t2.c
$ ./t2
Enter year: 2013
Enter day of the year: 1
The date for that day of the year is Tue Jan  1 00:00:00 2013
$ ./t2
Enter year: 2013
Enter day of the year: 365
The date for that day of the year is Tue Dec 31 00:00:00 2013

甚至适用于2012年这样的闰年:

$ ./t2
Enter year: 2012
Enter day of the year: 366
The date for that day of the year is Mon Dec 31 00:00:00 2012

因此,计算这一点的基本原则是有一个"每月天数"的列表。

int days_in_month[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

如果我们有一个名为days的变量,它是一年中的天数,month表示我们在哪个月结束:

从"month=1;"开始,只需检查days是否小于days_in_month[month],如果不是从天数中减去days_in_month[month],并继续进行,直到你达到月=12,仍然有更多的天数,天数超过了days_in_month[month][这意味着这是明年,从month=1开始,然后转到下一个year-但我认为你的任务限制在1-365天,所以现在只需报告错误就可以了]。

当天数不超过days_in_month[month]时,即为当月的天数。

请注意,我有意而不是编写了如何做到这一点的代码,而是描述了如何做到。因为我是至少写过几次这种代码的人,而你是试图学习的人。你不能通过复制和粘贴SO学习。

编辑:是的,我完全忽略了闰年。对于2013年来说,这不是闰年,所以我们不在乎…;)