পিএইচপি ডেটটাইম :: মাস যোগ এবং বিয়োগ করে সংশোধন করুন


101

আমি এর সাথে প্রচুর পরিশ্রম করে চলেছি 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

এটিকে ত্রুটি হিসাবে বিবেচনা করা হয়নি কেন কেউ ন্যায়সঙ্গত করতে পারেন?

তদ্ব্যতীত কারও কাছে সমস্যাটি সংশোধন করতে এত সুন্দর সমাধান আছে এবং এটিকে +1 মাসটি প্রত্যাশার পরিবর্তে প্রত্যাশার বদলে কাজ করবে?


"2001-01-31" প্লাস 1 মাস আপনি কী আশা করবেন? ... "2001-02-28"? "2001-03-01"?
আর্টেফ্যাক্টো

57
ব্যক্তিগতভাবে আমি এটি 2001-02-28 হওয়ার আশা করব।
প্লাজক

সঙ্গে একই গল্প strtotime() stackoverflow.com/questions/7119777/...
ভ্যালেন্টিন Despa

2
হ্যাঁ, এটি বেশ বিরক্তিকর স্পর্শকাতর। আপনি পি 1 এম 31 দিনের মতো তা বের করার জন্য সূক্ষ্ম মুদ্রণটি পড়েছেন। লোকেরা কেন এটি "সঠিক" আচরণ হিসাবে রক্ষা করে তা সত্যিই বুঝতে পারি না।
দেব

জনপ্রিয় মতামত বলে মনে হচ্ছে যে পিএইচপি রাউন্ড আপ (3/1 পর্যন্ত) যদিও লজিকটি গোল হয়ে যেতে হবে ... যদিও আমি পিএইচপি-র উপায় পছন্দ করি তবে মাইক্রোসফ্টের এক্সেল রাউন্ড ডাউন হয়ে স্প্রেডশিট ব্যবহারকারীদের বিরুদ্ধে ওয়েব বিকাশকারীকে পট করে দেয় ...
ডেভ হেক

উত্তর:


106

এটি কোনও বাগ নয় কেন:

বর্তমানের আচরণটি সঠিক। নিম্নলিখিত অভ্যন্তরীণভাবে ঘটে:

  1. +1 monthএক মাসের মাসের সংখ্যা (মূলত 1) বৃদ্ধি করে। এটি তারিখটি তৈরি করে 2010-02-31

  2. দ্বিতীয় মাসে (ফেব্রুয়ারিতে) কেবল ২০১০ সালে ২৮ দিন রয়েছে, তাই পিএইচপি এইচ-ফেব্রুয়ারি থেকে কেবল দিন গণনা অব্যাহত রেখে এটিকে সংশোধন করে। তারপরে আপনি ২ য় মার্চ শেষ করেছেন।

আপনি যা চান তা কীভাবে পাবেন:

আপনি যা চান তা পেতে: পরের মাসে ম্যানুয়ালি পরীক্ষা করা। তারপরে পরবর্তী মাসের দিনগুলির সংখ্যা যুক্ত করুন।

আমি আশা করি আপনি নিজেই এটি কোড করতে পারেন। আমি শুধু করণীয় দিচ্ছি।

পিএইচপি 5.3 উপায়:

সঠিক আচরণটি পেতে, আপনি পিএইচপি 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। নিম্নলিখিত পদগুলি যখন পিএইচপি এই first day of next monthস্তরের প্রক্রিয়া করে :

  1. next monthএক মাসের মাসের সংখ্যা (মূলত 1) বৃদ্ধি করে। এটি 2010-02-31 তারিখটি তৈরি করে।

  2. first day ofদিন সংখ্যাটি এতে সেট করে 1, যার ফলাফল 2010-02-01 তারিখের।


1
সুতরাং আপনি যা বলছেন তা কি পুরোপুরি দিনগুলি উপেক্ষা করে আক্ষরিকভাবে 1 মাস যুক্ত করেছে? সুতরাং আমি ধরে নিচ্ছি যে আপনি যদি লিপ বছরের পরে এটি যুক্ত করেন তবে আপনি +1 বছর একই ধরণের সমস্যার মধ্যে চলে যেতে পারেন?
30:51

@ পরিবর্তন, হ্যাঁ, এটি সাহিত্যে 1 মাস যুক্ত হয়
শিমিত্তোমর

13
এবং যদি আপনি এটি যুক্ত করার পরে 1 মাস বিয়োগ করে থাকেন তবে আপনি সম্পূর্ণ আলাদা তারিখটি শেষ করবেন, আমি ধরে নিই। এটা খুব অনর্থক বলে মনে হচ্ছে।
ড্যান ব্রেন

2
পিএইচপি 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

আমাদের ব্যবহারকারী একই দিনে উভয় নিউজলেটার পেলে ব্যতীত এটি ঠিক থাকবে। আসুন ধরে নেওয়া যাক এটি ডিমান্ড-পার্শ্বের পরিবর্তে সরবরাহের দিকের একটি সমস্যা worried আমরা উদ্বিগ্ন নই যে ব্যবহারকারী একই দিনে ২ টি নিউজলেটার পেয়ে ক্রুদ্ধ হবেন তবে এর পরিবর্তে আমাদের মেল সার্ভারগুলি ব্যান্ডউইথকে দ্বিগুণ প্রেরণের জন্য ব্যয় করতে পারে না অনেক নিউজলেটার। এই বিষয়টি মাথায় রেখে আমরা "+1 মাস" এর "অন্য মাসে দ্বিতীয় মাসের শেষের দিকে প্রেরণ করুন" এর অন্য ব্যাখ্যায় ফিরে যাই যা ফিরে আসবে:

  • 2015-01-30
  • 2015-02-27
  • 2015-03-30
  • 2015-04-29
  • 2015-05-30
  • 2015-06-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 দিন) এর মধ্যে রয়েছে।
  • তাদের উত্তরসূরি এবং পূর্বসূরীর সমস্ত কমপক্ষে ২৮ দিন (একটি চন্দ্র মাস), তাই খুব সমানভাবে বিতরণ করা হয়।

শেষ দুটি সেট দেওয়া, এটি যদি পরের মাসের বাইরে থেকে পড়ে যায় তবে খেজুরগুলির কোনওটির পিছনে ফিরে যাওয়া কঠিন হবে না (সুতরাং প্রথম সেটে ২৮ শে ফেব্রুয়ারি এবং ৩০ শে এপ্রিল ফিরে যান) এবং কোনও ঘুম না হারালে "মাসের শেষ দিন" বনাম "মাসের দ্বিতীয় দিন থেকে শেষ দিনের" প্যাটার্ন থেকে মাঝে মধ্যে ওভারল্যাপ এবং বিচ্যুতি। তবে গ্রন্থাগারটি "সবচেয়ে সুন্দর / প্রাকৃতিক", "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

(আমার কোডটি একটি জগাখিচুড়ি এবং বহুবর্ষের দৃশ্যে কাজ করবে না the অন্তর্নিহিত ভিত্তিটি অক্ষত রাখার পরে আমি যে কাউকে সমাধানটিকে আরও মার্জিত কোডের সাথে পুনরায় লেখার জন্য স্বাগত জানাই, অর্থাত যদি +1 মাস কোনও ফানকি তারিখ ফিরিয়ে দেয় তবে ব্যবহার করুন পরিবর্তে +4 সপ্তাহ।)


4

আমি একটি ফাংশন তৈরি করেছি যা একটি ডেটইন্টারওয়াল ফেরত দেয় তা নিশ্চিত করে একটি মাস যুক্ত করা হয় যে পরের মাসে প্রদর্শিত হয় এবং তারপরের দিনগুলি সরিয়ে দেয় s

$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 শে তারিখের সাথে কাজ করছেন under এটা সর্বদা লাগে$createdDate এত দেরিতে "পুনরাবৃত্তি" তারিখগুলি কম মূল্যবোধের মাসগুলিতে এগিয়ে দেওয়া হওয়ায় তারা কম মানগুলিতে স্থানান্তরিত হবে না (উদাহরণস্বরূপ, সমস্ত 29 তম, 30 তম বা 31 তম পুনরাবৃত্তের তারিখগুলি শেষ পর্যন্ত ২৮ তমকে আটকে যাবে না) একটি নন-লিপ-ইয়ার ফেব্রুয়ারী মাধ্যমে)।

অ্যালগরিদম পরীক্ষা করার জন্য এখানে কিছু ড্রাইভার কোড রয়েছে:

$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

আপনি যদি কেবল এক মাস এড়িয়ে যাওয়া এড়াতে চান তবে আপনি তারিখটি বের করতে এবং পরের মাসে একটি লুপ চালাতে এই জাতীয় কিছু করতে পারেন এবং তারিখটি একের সাথে হ্রাস করতে এবং একটি বৈধ তারিখ পর্যন্ত পুনরায় যাচাই করা যেখানে স্ট্রোটোটাইমের জন্য বৈধ স্ট্রিং $ আর্টিং_ক্যালকুলেটেড mysql ডেটটাইম বা "এখন")। এটি মাসকে বাদ দেওয়ার পরিবর্তে 1 মিনিট থেকে মধ্যরাতে মাসের একেবারে শেষ খুঁজে পায়।

    $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

আমার 'গত বছর এই মাসের' জন্য একটি তারিখ পাওয়ার দরকার ছিল এবং এই মাসটি যখন ফেব্রুয়ারি মাসে লিপ বছরে হয় তখন তা খুব দ্রুত অপ্রীতিকর হয়ে ওঠে। তবে, আমি বিশ্বাস করি এটি কাজ করে ...: - / কৌশলটি মনে হয় আপনার মাসের প্রথম দিনটিকে আপনার পরিবর্তনকে ভিত্তি করে দিয়েছে।

$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
আপনার নিজের উত্তরটি ব্যাখ্যা করা দরকার। কোডের উত্তরগুলি কেবলমাত্র নিম্নমানের হিসাবে বিবেচিত হয়
মাচাভিটি

ধন্যবাদ! এটি এখনও নিকটতম উত্তর। আপনি যদি শেষ 2 টি লাইন স্যুইচ করেন তবে তা সর্বদা সঠিক মাস দেয়। যশ!
ড্যানি শোমন n

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()));

আপনি যদি ডেটটাইম ক্লাসটিও ব্যবহার করতে চান তবে এটি ঠিক আছে this আরও বিশদ এখানে


0

স্বীকৃত উত্তর ইতিমধ্যে ব্যাখ্যা করেছে যে এটি কেন নয় তবে এবং কিছু অন্যান্য উত্তর পিএইচপি মত প্রকাশের সাথে একটি ঝরঝরে সমাধান সমাধান করে first day of the +2 months । এই এক্সপ্রেশনগুলির সাথে সমস্যাটি হ'ল তারা স্বয়ংক্রিয়ভাবে পূর্ণ হয় না।

সমাধান যদিও বেশ সহজ। প্রথমত, আপনাকে দরকারী বিমূর্ততা খুঁজে পাওয়া উচিত যা আপনার সমস্যার স্থান প্রতিবিম্বিত করে। এই ক্ষেত্রে, এটি একটি ISO8601DateTime। দ্বিতীয়ত, একাধিক বাস্তবায়ন হওয়া উচিত যা পছন্দসই পাঠ্য উপস্থাপনা আনতে পারে। উদাহরণস্বরূপ, Today, Tomorrow, The first day of this month, Future- সব একটি নির্দিষ্ট বাস্তবায়ন প্রতিনিধিত্ব ISO8601DateTimeধারণা।

সুতরাং, আপনার ক্ষেত্রে, আপনার প্রয়োজন একটি বাস্তবায়ন TheFirstDayOfNMonthsLater। যে কোনও আইডিইতে সাবক্লাসের তালিকাটি দেখে এটি সন্ধান করা সহজ। কোডটি এখানে:

$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

এক মাসের শেষ দিনগুলির সাথে একই জিনিস। এই পদ্ধতির আরও উদাহরণের জন্য, এটি পড়ুন


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.