PHP DateTime :: जोड़ने और घटाना महीनों को संशोधित करें


102

मैं बहुत से काम कर रहा हूं DateTime classऔर हाल ही में महीनों से जोड़ते समय मुझे लगा कि मैं एक बग था। थोड़ा शोध के बाद, यह प्रतीत होता है कि यह बग नहीं था, बल्कि इसके अनुसार काम करना था। यहां पाए गए दस्तावेज के अनुसार :

उदाहरण # 2 महीनों को जोड़ते या घटाते समय सावधान रहें

<?php
$date = new DateTime('2000-12-31');

$date->modify('+1 month');
echo $date->format('Y-m-d') . "\n";

$date->modify('+1 month');
echo $date->format('Y-m-d') . "\n";
?>
The above example will output:
2001-01-31
2001-03-03

क्या कोई इस बात को सही ठहरा सकता है कि इसे बग क्यों नहीं माना जाता?

इसके अलावा किसी के पास इस मुद्दे को ठीक करने और इसे बनाने के लिए कोई भी सुंदर समाधान है।


आप क्या उम्मीद करेंगे "2001-01-31" प्लस 1 महीना होगा? ... "2001-02-28"? "2001/03/01"?
आर्टीफैक्टो

57
व्यक्तिगत रूप से मुझे उम्मीद है कि यह 2001-02-28 होगा।
tplaner

के साथ भी यही कहानी strtotime() stackoverflow.com/questions/7119777/...
वैलेन्टिन Despa

2
हाँ, यह काफी कष्टप्रद है। आपने ठीक प्रिंट पढ़ लिया है कि P1M 31 दिन है। वास्तव में समझ में नहीं आता कि लोग इसे "सही" व्यवहार के रूप में बचाव क्यों करते हैं।
इंडिविज़न देव

ऐसा लगता है कि लोकप्रिय राय यह है कि तर्क को नीचे (2/28 तक) होना चाहिए, हालांकि PHP राउंड अप (3/1) ... हालांकि मैं PHP का तरीका पसंद करता हूं, लेकिन Microsoft का एक्सेल गोल नीचे, वेब डेवलपर्स को स्प्रेडशीट उपयोगकर्ताओं के खिलाफ खड़ा करता है ...
डेव हेक

जवाबों:


107

यह बग क्यों नहीं है:

वर्तमान व्यवहार सही है। निम्नलिखित आंतरिक रूप से होता है:

  1. +1 monthमहीने की संख्या (मूल रूप से 1) को एक बढ़ाता है। यह तारीख बनाता है 2010-02-31

  2. दूसरे महीने (फरवरी) के 2010 में केवल 28 दिन हैं, इसलिए PHP ने इसे 1 फरवरी से दिन गिनने के लिए जारी रखा है। आप तब 3 मार्च को समाप्त होते हैं।

आप जो चाहते हैं उसे कैसे प्राप्त करें:

जो आप चाहते हैं उसे पाने के लिए: अगले महीने मैन्युअल रूप से जाँच करें। फिर अगले महीने के दिनों की संख्या जोड़ें।

मुझे उम्मीद है कि आप स्वयं इसे कोड कर सकते हैं। मैं सिर्फ क्या-क्या कर रहा हूं।

PHP 5.3 रास्ता:

सही व्यवहार प्राप्त करने के लिए, आप PHP 5.3 की नई कार्यक्षमता में से एक का उपयोग कर सकते हैं जो सापेक्ष समय श्लोक का परिचय देता है first day of। यह श्लोक के साथ संयोजन में इस्तेमाल किया जा सकता next month, fifth monthया +8 monthsनिर्दिष्ट महीने के पहले दिन पर जाने के लिए। इसके बजाय +1 monthकि आप क्या कर रहे हैं, आप इस कोड का उपयोग अगले महीने के पहले दिन के लिए इस तरह कर सकते हैं:

<?php
$d = new DateTime( '2010-01-31' );
$d->modify( 'first day of next month' );
echo $d->format( 'F' ), "\n";
?>

यह स्क्रिप्ट सही तरीके से आउटपुट करेगी February। निम्न बातें तब होती हैं जब PHP इस first day of next monthश्लोक को संसाधित करता है :

  1. next monthमहीने की संख्या (मूल रूप से 1) को एक बढ़ाता है। यह 2010-02-31 की तारीख बनाती है।

  2. first day ofदिन की संख्या को सेट करता है 1, जिसके परिणामस्वरूप दिनांक 2010-02-01 है।


1
तो क्या आप कह रहे हैं कि यह सचमुच 1 महीने जोड़ता है, दिनों को पूरी तरह से अनदेखा करता है? तो मैं मान रहा हूँ कि यदि आप इसे लीप वर्ष के दौरान जोड़ते हैं तो आप +1 वर्ष के साथ समान मुद्दे पर चल सकते हैं?
16

@ हल, हां, यह साहित्यिक 1 महीने जोड़ता है।
शामतोमर

13
और अगर आप इसे जोड़ने के 1 महीने बाद घटाते हैं, तो आप पूरी तरह से एक अलग तारीख के साथ समाप्त होते हैं, मुझे लगता है। जो बहुत अचूक लगता है।
डैन ब्रिन

2
PHP के 5.3 में नए श्लोक का उपयोग करने के बारे में बहुत बढ़िया उदाहरण है जहां आप पहले दिन, आखिरी दिन, इस महीने, अगले महीने और पिछले महीने का उपयोग कर सकते हैं।
किम स्टैक

6
imho यह एक बग है। एक गंभीर बग। अगर मैं 31 दिन जोड़ना चाहता हूं, तो मैं 31 दिन जोड़ता हूं। II एक महीना जोड़ना चाहता है, एक महीना जोड़ा जाना चाहिए, 31 दिन नहीं।
low_rents

12

यह पूरी तरह से डेटाइम तरीकों का उपयोग करते हुए एक और कॉम्पैक्ट समाधान है, जो क्लोन बनाने के बिना ऑब्जेक्ट को जगह में संशोधित करता है।

$dt = new DateTime('2012-01-31');

echo $dt->format('Y-m-d'), PHP_EOL;

$day = $dt->format('j');
$dt->modify('first day of +1 month');
$dt->modify('+' . (min($day, $dt->format('t')) - 1) . ' days');

echo $dt->format('Y-m-d'), PHP_EOL;

यह आउटपुट:

2012-01-31
2012-02-29

1
धन्यवाद। यहां अब तक का सबसे अच्छा समाधान। आप कोड को छोटा भी कर सकते हैं $dt->modify()->modify()। साथ ही काम करता है।
अल्फ.डेव

10

यह उपयोगी हो सकता है:

echo Date("Y-m-d", strtotime("2013-01-01 +1 Month -1 Day"));
  // 2013-01-31

echo Date("Y-m-d", strtotime("2013-02-01 +1 Month -1 Day"));
  // 2013-02-28

echo Date("Y-m-d", strtotime("2013-03-01 +1 Month -1 Day"));
  // 2013-03-31

echo Date("Y-m-d", strtotime("2013-04-01 +1 Month -1 Day"));
  // 2013-04-30

echo Date("Y-m-d", strtotime("2013-05-01 +1 Month -1 Day"));
  // 2013-05-31

echo Date("Y-m-d", strtotime("2013-06-01 +1 Month -1 Day"));
  // 2013-06-30

echo Date("Y-m-d", strtotime("2013-07-01 +1 Month -1 Day"));
  // 2013-07-31

echo Date("Y-m-d", strtotime("2013-08-01 +1 Month -1 Day"));
  // 2013-08-31

echo Date("Y-m-d", strtotime("2013-09-01 +1 Month -1 Day"));
  // 2013-09-30

echo Date("Y-m-d", strtotime("2013-10-01 +1 Month -1 Day"));
  // 2013-10-31

echo Date("Y-m-d", strtotime("2013-11-01 +1 Month -1 Day"));
  // 2013-11-30

echo Date("Y-m-d", strtotime("2013-12-01 +1 Month -1 Day"));
  // 2013-12-31

2
सामान्य समाधान नहीं है, क्योंकि यह केवल कुछ इनपुट के लिए काम करता है, जैसे कि महीने का 1। उदाहरण के लिए 30 जनवरी को ऐसा करने से दुख होता है।
जेन्स रोलैंड

या आप कर सकते हैं$dateTime->modify('first day of next month')->modify('-1day')
एंथनी

6

समस्या का मेरा समाधान:

$startDate = new \DateTime( '2015-08-30' );
$endDate = clone $startDate;

$billing_count = '6';
$billing_unit = 'm';

$endDate->add( new \DateInterval( 'P' . $billing_count . strtoupper( $billing_unit ) ) );

if ( intval( $endDate->format( 'n' ) ) > ( intval( $startDate->format( 'n' ) ) + intval( $billing_count ) ) % 12 )
{
    if ( intval( $startDate->format( 'n' ) ) + intval( $billing_count ) != 12 )
    {
        $endDate->modify( 'last day of -1 month' );
    }
}

3
"क्लोन" कमांड मेरे वैरिएबल असाइनमेंट समस्याओं का समाधान था। इसके लिए शुक्रिया।
स्टीफ रोज

4

मैं ओपी की भावना से सहमत हूं कि यह प्रति-सहज और निराशाजनक है, लेकिन यह निर्धारित कर रहा +1 monthहै कि परिदृश्य में क्या होता है। इन उदाहरणों पर विचार करें:

आप 2015-01-31 से शुरू करते हैं और ईमेल न्यूज़लेटर भेजने के लिए शेड्यूलिंग चक्र प्राप्त करने के लिए 6 महीने जोड़ना चाहते हैं। ओपी की शुरुआती उम्मीदों को ध्यान में रखते हुए, यह वापसी करेगा:

  • 2015-01-31
  • 2015-02-28
  • 2015/03/31
  • 2015/04/30
  • 2015/05/31
  • 2015/06/30

यह करते ही हमें जो सूचना उम्मीद कर रहे हैं +1 monthमतलब करने के लिए last day of monthया वैकल्पिक रूप से यात्रा प्रति लेकिन हमेशा प्रारंभ बिंदु के संदर्भ में 1 महीने जोड़ने के लिए। इसे "महीने के अंतिम दिन" के रूप में व्याख्या करने के बजाय, हम इसे "अगले महीने के 31 वें दिन या उस महीने के भीतर उपलब्ध अंतिम" के रूप में पढ़ सकते हैं। इसका मतलब है कि हम 30 मई के बजाय 30 अप्रैल से 31 मई तक कूदेंगे। ध्यान दें कि यह इसलिए नहीं है क्योंकि यह "महीने का अंतिम दिन" है, लेकिन क्योंकि हम चाहते हैं कि "महीने की शुरुआत से सबसे करीबी उपलब्ध हो।"

तो मान लीजिए कि हमारा एक उपयोगकर्ता 2015-01-30 को शुरू करने के लिए किसी अन्य समाचार पत्र की सदस्यता लेता है। के लिए सहज तिथि क्या है +1 month? एक व्याख्या "अगले महीने के 30 वें दिन या निकटतम उपलब्ध होगी" जो वापस आ जाएगी:

  • 2015-01-30
  • 2015-02-28
  • 2015/03/30
  • 2015/04/30
  • 2015/05/30
  • 2015/06/30

यह तब ठीक होगा जब हमारे उपयोगकर्ता को उसी दिन दोनों समाचार पत्र प्राप्त होंगे। मान लें कि यह डिमांड-साइड के बजाय एक आपूर्ति-पक्ष का मुद्दा है, हम चिंतित नहीं हैं कि उपयोगकर्ता एक ही दिन में 2 समाचार पत्र प्राप्त करने से नाराज हो जाएगा, लेकिन इसके बजाय हमारे मेल सर्वर दो बार भेजने के लिए बैंडविड्थ का जोखिम नहीं उठा सकते हैं कई समाचार पत्र। इसे ध्यान में रखते हुए, हम "+1 महीने" की अन्य व्याख्या पर वापस लौटते हैं, जैसे "प्रत्येक महीने के दूसरे से अंतिम दिन पर भेजें":

  • 2015-01-30
  • 2015-02-27
  • 2015/03/30
  • 2015/04/29
  • 2015/05/30
  • 2015/06/29

अब हम पहले सेट के साथ किसी भी ओवरलैप से बच गए हैं, लेकिन हम अप्रैल और जून 29 के साथ भी समाप्त होते हैं, जो निश्चित रूप से हमारे मूल अंतर्ज्ञान से मेल खाता है, जो कि सभी संभावित महीनों के लिए +1 monthबस वापस m/$d/Yया आकर्षक और सरल होना चाहिए m/30/Y। तो अब आइए +1 monthदोनों तिथियों के उपयोग की एक तीसरी व्याख्या पर विचार करें :

31 जनवरी

  • 2015-01-31
  • 2015-03-03
  • 2015/03/31
  • 2015/05/01
  • 2015/05/31
  • 2015/07/01

30 जनवरी

  • 2015-01-30
  • 2015-03-02
  • 2015/03/30
  • 2015/04/30
  • 2015/05/30
  • 2015/06/30

ऊपर कुछ मुद्दे हैं। फरवरी को छोड़ दिया जाता है, जो सप्लाई-एंड (यदि कोई मासिक बैंडविड्थ आवंटन है और फरवरी को बर्बाद हो जाता है और मार्च को दोगुना हो जाता है) और मांग-अंत (उपयोगकर्ताओं को फरवरी से धोखा महसूस होता है और अतिरिक्त मार्च का अनुभव होता है) दोनों की समस्या हो सकती है। गलती को सुधारने का प्रयास)। दूसरी ओर, ध्यान दें कि दो तारीखें निर्धारित हैं:

  • ओवरलैप कभी नहीं
  • हमेशा एक ही तारीख पर होते हैं जब उस महीने की तारीख होती है (इसलिए 30 जनवरी सेट बहुत साफ दिखता है)
  • सभी 3 दिनों के भीतर हैं (ज्यादातर मामलों में 1 दिन) जिसे "सही" तारीख माना जा सकता है।
  • सभी अपने उत्तराधिकारी और पूर्ववर्ती से कम से कम 28 दिन (एक चंद्र महीना) हैं, इसलिए बहुत समान रूप से वितरित किया जाता है।

पिछले दो सेटों को देखते हुए, किसी एक तारीख को वापस रोल करना मुश्किल नहीं होगा, अगर वह वास्तविक अगले महीने से बाहर हो जाती है (तो पहले सेट में 28 फरवरी और 30 अप्रैल को वापस रोल करें) और किसी भी नींद को न खोएं कभी-कभी ओवरलैप और "महीने के अंतिम दिन" बनाम "महीने के दूसरे से अंतिम दिन" पैटर्न के लिए विचलन। लेकिन लाइब्रेरी से "सबसे सुंदर / प्राकृतिक", "02/31 की गणितीय व्याख्या और अन्य महीने की अधिकता", और "महीने के पहले या आखिरी महीने के सापेक्ष" के बीच चयन करने की अपेक्षा करना हमेशा किसी की अपेक्षाओं के पूरा नहीं होने वाला है और "गलत" व्याख्या का परिचय देने वाली वास्तविक दुनिया की समस्या से बचने के लिए "गलत" तारीख को समायोजित करने के लिए कुछ अनुसूची की आवश्यकता होती है।

इसलिए फिर से, जबकि मैं यह भी उम्मीद करूंगा +1 monthकि वास्तव में अगले महीने एक तारीख वापस आ जाएगी , यह अंतर्ज्ञान जितना आसान नहीं है और विकल्प दिए गए हैं, वेब डेवलपर्स की अपेक्षाओं पर गणित के साथ जाना शायद सुरक्षित विकल्प है।

यहां एक वैकल्पिक समाधान है जो अभी भी किसी भी तरह से क्लूनी है लेकिन मुझे लगता है कि अच्छे परिणाम हैं:

foreach(range(0,5) as $count) {
    $new_date = clone $date;
    $new_date->modify("+$count month");
    $expected_month = $count + 1;
    $actual_month = $new_date->format("m");
    if($expected_month != $actual_month) {
        $new_date = clone $date;
        $new_date->modify("+". ($count - 1) . " month");
        $new_date->modify("+4 weeks");
    }
    
    echo "* " . nl2br($new_date->format("Y-m-d") . PHP_EOL);
}

यह इष्टतम नहीं है, लेकिन अंतर्निहित तर्क है: यदि अगले महीने की अपेक्षा किसी अन्य तिथि में 1 महीने के परिणाम जोड़ते हैं, तो उस तिथि को स्क्रैप करें और इसके बजाय 4 सप्ताह जोड़ें। यहां दो परीक्षा तिथियों के साथ परिणाम दिए गए हैं:

31 जनवरी

  • 2015-01-31
  • 2015-02-28
  • 2015/03/31
  • 2015/04/28
  • 2015/05/31
  • 2015/06/28

30 जनवरी

  • 2015-01-30
  • 2015-02-27
  • 2015/03/30
  • 2015/04/30
  • 2015/05/30
  • 2015/06/30

(मेरा कोड एक गड़बड़ है और एक बहु-वर्ष के परिदृश्य में काम नहीं करेगा। मैं किसी का भी स्वागत करता हूं कि समाधान को अधिक सुरुचिपूर्ण कोड के साथ फिर से लिखना जब तक अंतर्निहित आधार बरकरार रखा जाता है, यानी अगर +1 महीना एक कायरतापूर्ण रिटर्न देता है, तो उपयोग करें इसके बजाय +4 सप्ताह।)


4

मैंने एक फ़ंक्शन बनाया जो एक DateInterval देता है यह सुनिश्चित करने के लिए कि एक महीना जोड़ना अगले महीने दिखाता है, और उसके बाद के दिनों को हटा देता है।

$time = new DateTime('2014-01-31');
echo $time->format('d-m-Y H:i') . '<br/>';

$time->add( add_months(1, $time));

echo $time->format('d-m-Y H:i') . '<br/>';



function add_months( $months, \DateTime $object ) {
    $next = new DateTime($object->format('d-m-Y H:i:s'));
    $next->modify('last day of +'.$months.' month');

    if( $object->format('d') > $next->format('d') ) {
        return $object->diff($next);
    } else {
        return new DateInterval('P'.$months.'M');
    }
}

4

शामितोमर के जवाब के साथ संयोजन में, यह महीनों को "सुरक्षित रूप से" जोड़ने के लिए हो सकता है:

/**
 * Adds months without jumping over last days of months
 *
 * @param \DateTime $date
 * @param int $monthsToAdd
 * @return \DateTime
 */

public function addMonths($date, $monthsToAdd) {
    $tmpDate = clone $date;
    $tmpDate->modify('first day of +'.(int) $monthsToAdd.' month');

    if($date->format('j') > $tmpDate->format('t')) {
        $daysToAdd = $tmpDate->format('t') - 1;
    }else{
        $daysToAdd = $date->format('j') - 1;
    }

    $tmpDate->modify('+ '. $daysToAdd .' days');


    return $tmpDate;
}

बहुत बहुत धन्यवाद!!
geckos

2

मुझे निम्नलिखित कोड का उपयोग करके इसके चारों ओर एक छोटा रास्ता मिला:

                   $datetime = new DateTime("2014-01-31");
                    $month = $datetime->format('n'); //without zeroes
                    $day = $datetime->format('j'); //without zeroes

                    if($day == 31){
                        $datetime->modify('last day of next month');
                    }else if($day == 29 || $day == 30){
                        if($month == 1){
                            $datetime->modify('last day of next month');                                
                        }else{
                            $datetime->modify('+1 month');                                
                        }
                    }else{
                        $datetime->modify('+1 month');
                    }
echo $datetime->format('Y-m-d H:i:s');

1

यहाँ एक संबंधित प्रश्न में जुहाना के उत्तर के उन्नत संस्करण का कार्यान्वयन है :

<?php
function sameDateNextMonth(DateTime $createdDate, DateTime $currentDate) {
    $addMon = clone $currentDate;
    $addMon->add(new DateInterval("P1M"));

    $nextMon = clone $currentDate;
    $nextMon->modify("last day of next month");

    if ($addMon->format("n") == $nextMon->format("n")) {
        $recurDay = $createdDate->format("j");
        $daysInMon = $addMon->format("t");
        $currentDay = $currentDate->format("j");
        if ($recurDay > $currentDay && $recurDay <= $daysInMon) {
            $addMon->setDate($addMon->format("Y"), $addMon->format("n"), $recurDay);
        }
        return $addMon;
    } else {
        return $nextMon;
    }
}

यह संस्करण $createdDateअनुमान के तहत लेता है कि आप एक आवर्ती मासिक अवधि के साथ काम कर रहे हैं, जैसे कि एक सदस्यता, जो एक विशिष्ट तिथि पर शुरू हुई, जैसे कि 31 वीं। यह हमेशा $createdDateइतनी देर से होता है "तारीखों पर पुनरावृत्ति" निम्न मानों पर शिफ्ट नहीं होगी क्योंकि उन्हें कम-मूल्यवान महीनों के लिए आगे बढ़ाया जाता है (उदाहरण के लिए, इसलिए सभी 29, 30 या 31 वीं पुनरावृत्ति तिथियां अंततः पारित होने के बाद 28 वें पर अटक नहीं जाएंगी गैर-लीप-वर्ष फरवरी के माध्यम से)।

एल्गोरिथ्म का परीक्षण करने के लिए यहां कुछ ड्राइवर कोड दिए गए हैं:

$createdDate = new DateTime("2015-03-31");
echo "created date = " . $createdDate->format("Y-m-d") . PHP_EOL;

$next = sameDateNextMonth($createdDate, $createdDate);
echo "   next date = " . $next->format("Y-m-d") . PHP_EOL;

foreach(range(1, 12) as $i) {
    $next = sameDateNextMonth($createdDate, $next);
    echo "   next date = " . $next->format("Y-m-d") . PHP_EOL;
}

कौन से आउटपुट:

created date = 2015-03-31
   next date = 2015-04-30
   next date = 2015-05-31
   next date = 2015-06-30
   next date = 2015-07-31
   next date = 2015-08-31
   next date = 2015-09-30
   next date = 2015-10-31
   next date = 2015-11-30
   next date = 2015-12-31
   next date = 2016-01-31
   next date = 2016-02-29
   next date = 2016-03-31
   next date = 2016-04-30

1

यह संबंधित प्रश्न में कटिहासी के उत्तर का एक उन्नत संस्करण है । यह सही ढंग से महीनों की एक मनमानी संख्या को जोड़ या घटा देगा।

public static function addMonths($monthToAdd, $date) {
    $d1 = new DateTime($date);

    $year = $d1->format('Y');
    $month = $d1->format('n');
    $day = $d1->format('d');

    if ($monthToAdd > 0) {
        $year += floor($monthToAdd/12);
    } else {
        $year += ceil($monthToAdd/12);
    }
    $monthToAdd = $monthToAdd%12;
    $month += $monthToAdd;
    if($month > 12) {
        $year ++;
        $month -= 12;
    } elseif ($month < 1 ) {
        $year --;
        $month += 12;
    }

    if(!checkdate($month, $day, $year)) {
        $d2 = DateTime::createFromFormat('Y-n-j', $year.'-'.$month.'-1');
        $d2->modify('last day of');
    }else {
        $d2 = DateTime::createFromFormat('Y-n-d', $year.'-'.$month.'-'.$day);
    }
    return $d2->format('Y-m-d');
}

उदाहरण के लिए:

addMonths(-25, '2017-03-31')

उत्पादन होगा:

'2015-02-28'

0

यदि आप सिर्फ एक महीने के स्किपिंग से बचना चाहते हैं, तो आप कुछ ऐसा प्रदर्शन कर सकते हैं कि तारीख को प्राप्त करने के लिए और अगले महीने एक लूप को चलाकर तारीख को घटा सकते हैं और एक वैध तारीख तक रीचेक कर सकते हैं, जहां $ start_calculated strtime के लिए एक वैध स्ट्रिंग है (यानी mysql डेटाइम या "अब")। यह महीने के अंत को महीने को लंघन के बजाय आधी रात से आधी रात तक पाता है।

    $start_dt = $starting_calculated;

    $next_month = date("m",strtotime("+1 month",strtotime($start_dt)));
    $next_month_year = date("Y",strtotime("+1 month",strtotime($start_dt)));

    $date_of_month = date("d",$starting_calculated);

    if($date_of_month>28){
        $check_date = false;
        while(!$check_date){
            $check_date = checkdate($next_month,$date_of_month,$next_month_year);
            $date_of_month--;
        }
        $date_of_month++;
        $next_d = $date_of_month;
    }else{
        $next_d = "d";
    }
    $end_dt = date("Y-m-$next_d 23:59:59",strtotime("+1 month"));



0

मुझे 'इस महीने पिछले साल' के लिए एक तारीख पाने की ज़रूरत थी और यह एक छलांग वर्ष में फरवरी के महीने में बहुत जल्दी अप्रिय हो जाती है। हालाँकि, मेरा मानना ​​है कि यह काम करता है ...: - / चाल महीने के 1 दिन में आपके बदलाव को आधार बनाती है।

$this_month_last_year_end = new \DateTime();
$this_month_last_year_end->modify('first day of this month');
$this_month_last_year_end->modify('-1 year');
$this_month_last_year_end->modify('last day of this month');
$this_month_last_year_end->setTime(23, 59, 59);

0
$ds = new DateTime();
$ds->modify('+1 month');
$ds->modify('first day of this month');

1
आपको अपना उत्तर समझाने की आवश्यकता है। कोड केवल जवाब कम गुणवत्ता माना जाता है
Machavity

धन्यवाद! यह अभी तक का सबसे साफ जवाब है। यदि आप अंतिम 2 लाइनों को स्विच करते हैं तो यह हमेशा सही महीना देता है। कुडोस!
डैनी शोमैन

0
$month = 1; $year = 2017;
echo date('n', mktime(0, 0, 0, $month + 2, -1, $year));

आउटपुट 2(फरवरी) होगा। अन्य महीनों के लिए भी काम करेंगे।


0
$current_date = new DateTime('now');
$after_3_months = $current_date->add(\DateInterval::createFromDateString('+3 months'));

दिनों के लिए:

$after_3_days = $current_date->add(\DateInterval::createFromDateString('+3 days'));

जरूरी:

add()डेटटाइम क्लास की विधि ऑब्जेक्ट वैल्यू को संशोधित करती है इसलिए add()डेटटाइम ऑब्जेक्ट पर कॉल करने के बाद यह नई तिथि ऑब्जेक्ट लौटाता है और यह ऑब्जेक्ट को स्वयं भी संशोधित करता है।


0

आप वास्तव में इसे सिर्फ तारीख () और स्ट्रेटटाइम () के साथ भी कर सकते हैं। उदाहरण के लिए आज की तारीख में 1 महीने जोड़ने के लिए:

date("Y-m-d",strtotime("+1 month",time()));

अगर आप डेटाइम क्लास का उपयोग करना चाहते हैं, तो यह ठीक है लेकिन यह उतना ही आसान है। अधिक जानकारी यहाँ


0

स्वीकृत उत्तर पहले से ही समझाता है कि यह क्यों नहीं है, लेकिन कुछ अन्य जवाब जैसे php भावों के साथ एक साफ समाधान प्रस्तुत करते हैं first day of the +2 months । उन भावों के साथ समस्या यह है कि वे स्वत: स्फूर्त नहीं हैं।

समाधान हालांकि काफी सरल है। सबसे पहले, आपको उपयोगी अमूर्तियां ढूंढनी चाहिए जो आपकी समस्या को दर्शाती हैं। इस मामले में, यह एक है ISO8601DateTime। दूसरा, कई कार्यान्वयन होने चाहिए जो एक वांछित पाठात्मक प्रतिनिधित्व ला सकते हैं। उदाहरण के लिए, Today, Tomorrow, The first day of this month, Future- सभी का एक विशिष्ट कार्यान्वयन का प्रतिनिधित्व ISO8601DateTimeअवधारणा।

तो, आपके मामले में, एक कार्यान्वयन जिसकी आपको आवश्यकता है TheFirstDayOfNMonthsLater। किसी भी IDE में उपवर्गों की सूची को देखकर इसे ढूंढना आसान है। यहाँ कोड है:

$start = new DateTimeParsedFromISO8601String('2000-12-31');
$firstDayOfOneMonthLater = new TheFirstDayOfNMonthsLater($start, 1);
$firstDayOfTwoMonthsLater = new TheFirstDayOfNMonthsLater($start, 2);
var_dump($start->value()); // 2000-12-31T00:00:00+00:00
var_dump($firstDayOfOneMonthLater->value()); // 2001-01-01T00:00:00+00:00
var_dump($firstDayOfTwoMonthsLater->value()); // 2001-02-01T00:00:00+00:00

महीने के आखिरी दिनों के साथ भी यही बात। इस दृष्टिकोण के अधिक उदाहरणों के लिए, इसे पढ़ें


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.