0

20130228などの長い値で日付を保存していて、30日や50を追加するなどの操作を実行する必要があります。より適切なものに変換する方法について何か提案はありますか?

4

3 に答える 3

4

このように保管すれば

unsigned long d = 20130228;

最初に簡単な算術で分割して、struct tm

struct tm tm;
tm.tm_year = d / 10000 - 1900;
tm.tm_mon = (d % 10000) / 100 - 1;
tm.tm_mday = d % 100;
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
tm.tm_isdst = -1;

30次に、に値を追加できますtm.tm_mday。を使用すると、エポックとのフィールドが正規化されるため、秒としてmktime()受け取ります。time_ttm

time_t t = mktime(&tm);
于 2013-02-28T11:22:02.030 に答える
1

年、月、日を抽出してから、各月の日数とうるう年を考慮して日を追加することができます。

#include <stdio.h>

unsigned long AddDays(unsigned long StartDay, unsigned long Days)
{
  unsigned long year = StartDay / 10000, month = StartDay / 100 % 100 - 1, day = StartDay % 100 - 1;

  while (Days)
  {
    unsigned daysInMonth[2][12] =
    {
      { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, // 365 days, non-leap
      { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }  // 366 days, leap
    };

    int leap = !(year % 4) && (year % 100 || !(year % 400));

    unsigned daysLeftInMonth = daysInMonth[leap][month] - day;

    if (Days >= daysLeftInMonth)
    {
      day = 0;
      Days -= daysLeftInMonth;
      if (++month >= 12)
      {
        month = 0;
        year++;
      }
    }
    else
    {
      day += Days;
      Days = 0;
    }
  }

  return year * 10000 + (month + 1) * 100 + day + 1;
}

int main(void)
{
  unsigned long testData[][2] =
  {
    { 20130228, 0 },
    { 20130228, 1 },
    { 20130228, 30 },
    { 20130228, 31 },
    { 20130228, 32 },
    { 20130228, 365 },
    { 20130228, 366 },
    { 20130228, 367 },
    { 20130228, 365*3 },
    { 20130228, 365*3+1 },
    { 20130228, 365*3+2 },
  };

  unsigned i;

  for (i = 0; i < sizeof(testData) / sizeof(testData[0]); i++)
    printf("%lu + %lu = %lu\n", testData[i][0], testData[i][1], AddDays(testData[i][0], testData[i][1]));

  return 0;
}

出力(ideone):

20130228 + 0 = 20130228
20130228 + 1 = 20130301
20130228 + 30 = 20130330
20130228 + 31 = 20130331
20130228 + 32 = 20130401
20130228 + 365 = 20140228
20130228 + 366 = 20140301
20130228 + 367 = 20140302
20130228 + 1095 = 20160228
20130228 + 1096 = 20160229
20130228 + 1097 = 20160301

別のオプションは、年、月、日を抽出し、または同様の関数epochを使用してから秒に変換しmktime()、その秒数に、指定された日付からのそれらの日を表す秒数を追加して、結果の秒を元に戻すことです。gmtime()またはlocaltime()または同様の関数を使用して日付に入力し、長整数値を作成します。タイムゾーンや夏時間などを避けるために、これらの関数を使用しないことを選択しました。シンプルで封じ込められたソリューションが欲しかった。

于 2013-02-28T12:02:34.877 に答える
0

日付を「Xからの時間の単位」に変換することで、日付の「計算」を行うのがはるかに簡単になる傾向があります。time_t標準ライブラリでは、「1970年1月1日の深夜からの秒数」です。したがって、mktimefromを使用するstruct tmことが1つの解決策になります。

何らかの理由でそれを望まない場合は、日付を「(たとえば)2000年1月1日からの日数」に変換すると機能します。年間を処理するときは、飛躍年を考慮に入れる必要があります(year % 4 == 0 && (year % 100 != 0 || year %400 == 0)それをカバーする必要があります)。もちろん、1年以内に、1か月あたりの日数に注意する必要があります。現在までの変換は似ていますが、逆です。

于 2013-02-28T12:01:19.293 に答える