Süresinin eklenmesi sorunlar

3 Cevap php

Zamanla bazı matematik yaparken ben bir garip timewarp çalıştırmak, ve odunum beni terk etti. Ya da, iyi, ben nedenini (veya en azından makul bir) bulduk, ama oldukça bu konuda ne bilmiyorum, ya da yapılabilecek bir şey gerçekten varsa.

Düz bir deyişle konu 1 hafta daha büyük birimlerde zaman (o en çarpanları hariç) eklerken tam olması imkansız gibi görünüyor olmasıdır. Ve tam göre ben ŞİMDİ saniye 1 yıl değerinde eklediğinizde, ŞİMDİ 1 yıl ve birkaç saat sonuna kadar demek.

Ben bir ay boyu değişir olarak 1 (veya daha fazla) ay ekleyerek, bunu anlayabilirim, ama bir yıl bu olmamalı, daha fazla veya daha az aynı olmalıdır?

Şimdi ben bunu bilmek istiyorum biliyorum, bu nedenle burada (pseudoish) kodu aşağıdadır:

class My_DateInterval {
    public $length; // Interval length in seconds

    public function __construct($interval) {
        $this->length = 0;

        preg_match(
            '/P(((?<years>([0-9]{1,}))Y)|((?<months>([0-9]{1,}))M)|((?<weeks>([0-9]{1,}))W)|((?<days>([0-9]{1,}))D)){0,}(T((?<hours>([0-9]{1,2})){1}H){0,1}((?<minutes>([0-9]{1,2}){1})M){0,1}((?<seconds>([0-9]{1,2}){1})S){0,1}){0,1}/', 
            $interval, $timeparts
        );

        if (is_numeric($timeparts['years'])) $this->length += intval($timeparts['years']) * 31556926; // 1 year in seconds
        if (is_numeric($timeparts['months'])) $this->length += intval($timeparts['months']) * 2629743.83; // 1 month in seconds
        if (is_numeric($timeparts['weeks'])) $this->length += intval($timeparts['weeks']) * 604800; // 1 week in seconds
        if (is_numeric($timeparts['days'])) $this->length += intval($timeparts['days']) * 86400; // 1 day in seconds
        if (is_numeric($timeparts['hours'])) $this->length += intval($timeparts['hours']) * 3600; // 1 hour in seconds
        if (is_numeric($timeparts['minutes'])) $this->length += intval($timeparts['minutes']) * 60; // 1 minute in seconds
        if (is_numeric($timeparts['seconds'])) $this->length += intval($timeparts['seconds']);

        $this->length = round($this->length);
    }
}

class My_DateTime extends DateTime {
    public function __construct($time, $tz = null) {
        parent::__contruct($time, $tz);
    }

    public function add(My_DateInterval $i) {
        $this->modify($i->length . ' seconds');
    }
}

$d = new My_DateTime();
$i = new My_DateInterval('P1Y');
$d->add($i);

Değerler sonra "beklendiği gibi çalıştığını ve tüm kontrolleri dışarı" anlamında, tüm iyi, ancak yukarıda belirtilen sorun hala duruyor göstermek / önce aralık uzunluğu ve bazı hata ayıklama çıktılar yapmak: ve doğruluk bir anomali var ben çok mümkün olmadığını, sağ olsun istiyorum istiyorum hangi hepsi.

Kadar çok kelime: 1 hafta daha fazla zaman birimleri ile tam matematik yapmak için nasıl. (Yani 1 ay / 1 yıl).

PS. Ben My_ * sınıfları kullanıyorum neden merak edenler için PHP 5.3 yeterli yaygın değildir, çünkü, ama ben yerleşik yardımcı sınıflar için göç mümkün olduğunca düzgün olacak bir şekilde bir şeyler tutmaya çalışıyorum.

3 Cevap

Bir yıl kabaca 365.25 gün. Dolayısıyla biz sıçrama yıl var.

Ay değişken uzunlukları var.

Bu nedenle bir yıl eklenmesi ve bir ay ekleyerek ne semantik muhtemelen saniye sabit bir sayı ekleyerek karşılık gelmez.

14 Şubat 2007 için bir ay ekleyerek Örneğin muhtemelen 14 Mart 2007 verim beklenir ve 14th Şub 2008, sırasıyla 28 ya da 29 gün ekleyerek, 14 Mart 2008 ive olacaktır.

Bu şeyler farklı takvimler eklemek, özellikle gnarly alır, dünyanın pek gelmez bile have a Şubat! Sonra "Yedi Çalışma Günleri" eklemek - Eğer dikkate resmi tatil takvimi almak gerekir.

Bunun için bulabileceğiniz herhangi bir kütüphaneler var mı?

Ben bir ay boyu değişir olarak 1 (veya daha fazla) ay ekleyerek, bunu anlayabilirim, ama bir yıl bu olmamalı, daha fazla veya daha az aynı olmalıdır?

Eğer saniyelik bir yıllık değer eklerken yukarıda, sen günlerin sayısı ile başlıyoruz (ne sanırım) ve average yıl (yani, 365,2421 .. * 24 * 60 * 60 .) Yani hesaplama örtülü belirli bir gün sayısı olarak bir yıl tanımlar.

Bu tanım ile 31 Aralık biraz az 6 saat çok uzun. Yani "saat" 1 Ocak 00:00 üzerinde haddeleme önce (ne olursa olsun) 29:59 ile 31 Aralık 23:59 gider. 31 gün - Ayrıca yerine 28 saniye belirli bir sayıda olarak tanımlayan konum beri benzer bir şey, ay ile olur.

Lütfen hesaplama amacı genel bir "ortalama" takviminde olaylar arasındaki zamanlama farkı ise, daha sonra yöntem iyi çalışır. Eğer gerçek bir takvim ile bir yazışma olması gerekir ama, eğer kapalı olacak.

Bunu yapmak için basit yolu sahte Jülyen takvim kullanmaktır. Zaman (yıl, ay, gün, vb) her bölümü takip edin. Tam 24 saat olmak için gün tanımlayın. 365 gün bir yıl olarak tanımlayın. Yıl 4 ile bölünebilir ise 1 gün eklemek, ancak 100 ile bölünebilen olduğunda da 400 ile bölünebilen değil sürece.

Eklemek veya çıkarmak, elle "matematik" yapmak istiyorsanız ... Eğer artırmak her zaman, "taşma" için kontrol edin. Eğer ayın gününü taşma olursa, (sonra, vb taşma için aylık çek vb) sıfırlamak ve ay artırmak.

Sizin takvim hemen hemen her şey için, gerçek bir takvime tam olarak karşılık mümkün olacak.

Çoğu bilgisayar tarih uygulamaları (karmaşıklık değişen derecelerde) temelde bunu. Javascript, (örneğin benim web müfettiş kullanışlı olduğu için):

> new Date(2010,0,1,0,0,0) - new Date(2009,0,1,0,0,0)
31536000000

Gördüğünüz gibi, milisaniye tam 365 gün değer. Hiçbir karışıklık, hiçbir yaygara.

Onlar arada, zaman alma right HARD olduğunu. Matematik üssü 60 olduğunu. Tüm özel durumlar için (artık yıl, gün ışığından tasarruf, zaman dilimi) bulunuyor.

Eğlenin.

Birisi ilginizi sadece durumda, çalışan bir çözüm beni aptal hissettiriyor (her zamanki gibi) çok basitti. Bunun yerine saniye içine aralığı uzunluğunu tercüme, bir wordier versiyonu PHP internals ile düzgün çalışır.

class My_DateInterval {
    public $length; // strtotime supported string format
    public $years;
    public $months;
    public $weeks;
    public $days;
    public $hours;
    public $minutes;
    public $seconds;

    public function __construct($interval) {
        $this->length = 0;

        preg_match(
            '/P(((?<years>([0-9]{1,}))Y)|((?<months>([0-9]{1,}))M)|((?<weeks>([0-9]{1,}))W)|((?<days>([0-9]{1,}))D)){0,}(T((?<hours>([0-9]{1,2})){1}H){0,1}((?<minutes>([0-9]{1,2}){1})M){0,1}((?<seconds>([0-9]{1,2}){1})S){0,1}){0,1}/', 
            $interval, $timeparts
        );

        $this->years = intval($timeparts['years']);
        $this->months = intval($timeparts['months']);
        $this->weeks = intval($timeparts['weeks']);
        $this->days = intval($timeparts['days']);
        $this->hours = intval($timeparts['hours']);
        $this->minutes = intval($timeparts['minutes']);
        $this->seconds = intval($timeparts['seconds']);

        $length = $this->toString();
    }

    public function toString() {
        if (empty($this->length)) {
            $this->length =  sprintf('%d years %d months %d weeks %d days %d hours %d minutes %d seconds',
                $this->years,
                $this->months,
                $this->weeks,
                $this->days,
                $this->hours,
                $this->minutes,
                $this->seconds
            );
        }

        return $this->length;
    }
}