Dalam C # /. NET TimeSpan
memiliki TotalDays
,, TotalMinutes
dll. Tetapi saya tidak dapat menemukan rumus untuk perbedaan total bulan. Hari-hari variabel per bulan dan tahun kabisat terus mengusir saya. Bagaimana saya bisa mendapatkan TotalMonths ?
Sunting Maaf karena tidak lebih jelas: Saya tahu saya tidak bisa benar-benar mendapatkan ini dari TimeSpan
tetapi saya pikir menggunakan TotalDays
dan TotalMinutes
akan menjadi contoh yang baik untuk mengungkapkan apa yang saya cari ... kecuali saya sedang mencoba untuk mendapatkan Total Bulan.
Contoh: 25 Des 2009 - 6 Okt 2009 = 2 Total Bulan. 6 Oktober hingga 5 November sama dengan 0 bulan. Pada 6 November, 1 bulan. Pada 6 Desember, 2 bulan
Jawaban:
Anda tidak akan dapat memperolehnya dari a
TimeSpan
, karena "bulan" adalah satuan ukuran variabel. Anda harus menghitung sendiri, dan Anda harus mencari tahu bagaimana tepatnya Anda ingin itu berfungsi.Misalnya, haruskah tanggal menyukai
July 5, 2009
danAugust 4, 2009
menghasilkan perbedaan satu bulan atau nol bulan? Jika Anda mengatakan itu harus menghasilkan satu, lalu bagaimana denganJuly 31, 2009
danAugust 1, 2009
? Apakah itu sebulan? Apakah hanya perbedaanMonth
nilai untuk tanggal, atau lebih terkait dengan rentang waktu yang sebenarnya? Logika untuk menentukan semua aturan ini adalah non-sepele, jadi Anda harus menentukan sendiri dan mengimplementasikan algoritma yang sesuai.Jika semua yang Anda inginkan hanyalah perbedaan dalam bulan - sama sekali mengabaikan nilai tanggal - maka Anda dapat menggunakan ini:
Perhatikan bahwa ini mengembalikan perbedaan relatif, yang berarti bahwa jika
rValue
lebih besar darilValue
, maka nilai pengembalian akan negatif. Jika Anda menginginkan perbedaan mutlak, Anda dapat menggunakan ini:sumber
(Aku sadar ini pertanyaan lama, tapi ...)
Ini relatif menyakitkan untuk dilakukan di .NET murni. Saya akan merekomendasikan perpustakaan Noda Time saya sendiri , yang dirancang khusus untuk hal-hal seperti ini:
(Ada opsi lain, misalnya jika Anda hanya ingin hitungan bulan bahkan beberapa tahun, Anda akan menggunakan
Period period = Period.Between(start, end, PeriodUnits.Months);
)sumber
Period.Between
. Telah mengedit kode sehingga akan berfungsi dengan NodaTime 1.3.1.Mungkin Anda tidak ingin tahu tentang fraksi bulan; Bagaimana dengan kode ini?
sumber
Anda harus mendefinisikan apa yang Anda maksud dengan TotalMonths untuk memulai.
Sebuah definisi sederhana menempatkan satu bulan pada 30,4 hari (365.25 / 12).
Di luar itu, definisi apa pun termasuk fraksi tampaknya tidak berguna, dan nilai integer yang lebih umum (seluruh bulan antara tanggal) juga tergantung pada aturan bisnis yang tidak standar.
sumber
Saya telah menulis metode ekstensi yang sangat sederhana
DateTime
danDateTimeOffset
untuk melakukan ini. Saya ingin itu bekerja persis sepertiTotalMonths
properti yangTimeSpan
akan bekerja: yaitu mengembalikan hitungan bulan lengkap antara dua tanggal, mengabaikan setiap bulan parsial. Karena didasarkan padaDateTime.AddMonths()
itu menghormati panjang bulan yang berbeda dan mengembalikan apa yang manusia akan mengerti sebagai periode bulan.(Sayangnya Anda tidak dapat menerapkannya sebagai metode ekstensi di TimeSpan karena itu tidak mempertahankan pengetahuan tentang tanggal aktual yang digunakan, dan selama berbulan-bulan mereka penting.)
Kode dan tes keduanya tersedia di GitHub . Kode ini sangat sederhana:
Dan itu melewati semua kasus uji unit ini:
sumber
Anda harus menyelesaikannya sendiri di luar waktu data. Bagaimana Anda berurusan dengan hari rintisan pada akhirnya akan tergantung pada apa Anda ingin menggunakannya.
Salah satu metode adalah menghitung bulan dan kemudian mengoreksi hari di akhir. Sesuatu seperti:
sumber
Saya akan melakukannya seperti ini:
sumber
return (dtOther.Month - dtThis.Month) + 12 * (dtOther.Year - dtThis.Year);
Tidak ada banyak jawaban yang jelas tentang ini karena Anda selalu mengasumsikan sesuatu.
Solusi ini menghitung antara dua tanggal bulan antara asumsi Anda ingin menyimpan hari bulan untuk perbandingan, (artinya hari bulan dipertimbangkan dalam perhitungan)
Contoh, jika Anda memiliki tanggal 30 Jan 2012, 29 Feb 2012 tidak akan menjadi sebulan tetapi 01 Maret 2013
Ini sudah diuji cukup menyeluruh, mungkin akan membersihkannya nanti saat kita menggunakannya, dan mengambil dua tanggal bukannya Timespan, yang mungkin lebih baik. Semoga ini bisa membantu orang lain.
sumber
Jawaban yang diterima bekerja dengan sempurna ketika Anda ingin bulan penuh.
Saya membutuhkan sebagian bulan. Ini adalah solusi yang saya buat selama beberapa bulan:
Saya juga membutuhkan perbedaan tahun dengan kebutuhan yang sama untuk tahun parsial. Inilah solusi yang saya buat:
sumber
YearDifference
fungsi Anda ketikalValue.Month < rValue.Month
- Saya telah memperbaikinya sekarang, Anda mungkin ingin mengulas ...Pertanyaan lama yang saya tahu, tetapi mungkin bisa membantu seseorang. Saya telah menggunakan @Adam menerima jawaban di atas, tetapi kemudian memeriksa apakah perbedaannya adalah 1 atau -1 lalu memeriksa untuk melihat apakah perbedaan bulan penuh pada kalender. Jadi 21/07/55 dan 20/08/55 tidak akan menjadi satu bulan penuh, tetapi 21/07/55 dan 21/07/55 akan menjadi.
sumber
sumber
Masalah dengan bulan adalah bahwa itu bukan ukuran yang sederhana - mereka bukan ukuran konstan. Anda perlu menetapkan aturan untuk hal yang ingin Anda sertakan, dan bekerja dari sana. Misalnya 1 Jan hingga 1 Feb - Anda bisa berdebat 2 bulan terlibat di sana, atau bisa dibilang satu bulan. Lalu bagaimana dengan "1 Jan 20:00" hingga "1 Feb 00:00" - itu belum sebulan penuh. Apakah itu 0? 1? bagaimana dengan sebaliknya (1 Jan 00:00 hingga 1 Feb 20:00) ... 1? 2?
Pertama-tama tentukan aturannya, maka Anda harus membuat kode sendiri, saya khawatir ...
sumber
Jika Anda ingin memiliki hasil
1
antara28th Feb
dan1st March
:sumber
Pustaka ini menghitung selisih bulan, dengan mempertimbangkan semua bagian DateTime:
sumber
Di bawah ini sebenarnya adalah cara paling akurat yang dapat Anda lakukan, karena definisi "1 Bulan" berubah tergantung pada bulan itu, dan bukan jawaban lain yang memperhitungkannya! Jika Anda ingin informasi lebih lanjut tentang masalah yang tidak ada dalam kerangka kerja, Anda dapat membaca posting ini: Objek Timespan Nyata Dengan .Years & .Months (namun, membaca posting itu tidak perlu untuk memahami dan menggunakan fungsi di bawah ini, ini bekerja 100%, tanpa ketidakakuratan bawaan dari perkiraan yang suka digunakan orang lain - dan jangan ragu untuk mengganti fungsi .ReverseIt dengan built-in. Fungsi reverse yang mungkin Anda miliki pada kerangka kerja Anda (hanya ada di sini untuk kelengkapan).
Harap dicatat bahwa Anda bisa mendapatkan sejumlah tanggal / waktu akurasi, detik & menit, atau detik, menit dan hari, di mana saja hingga bertahun-tahun (yang akan mengandung 6 bagian / segmen). Jika Anda menentukan dua teratas dan lebih dari satu tahun, itu akan mengembalikan "1 tahun dan 3 bulan yang lalu" dan tidak akan mengembalikan sisanya karena Anda telah meminta dua segmen. jika hanya beberapa jam, maka itu hanya akan mengembalikan "2 jam dan 1 menit yang lalu". Tentu saja, aturan yang sama berlaku jika Anda menentukan 1, 2, 3, 4, 5 atau 6 segmet (maksimal 6 karena detik, menit, jam, hari, bulan, tahun hanya membuat 6 jenis). Itu juga akan memperbaiki masalah grammer seperti "menit" vs "menit" tergantung pada apakah itu 1 menit atau lebih, sama untuk semua jenis, dan "string" yang dihasilkan akan selalu benar secara tata bahasa.
Berikut adalah beberapa contoh untuk digunakan: bAllowSegments mengidentifikasi berapa banyak segmen yang ditampilkan ... yaitu: jika 3, maka kembalikan string akan menjadi (sebagai contoh) ...
"3 years, 2 months and 13 days"
(tidak akan memasukkan jam, menit dan detik sebagai 3 waktu teratas) kategori dikembalikan), namun jika tanggalnya adalah tanggal yang lebih baru, seperti sesuatu beberapa hari yang lalu, tentukan segmen yang sama (3) yang akan dikembalikan"4 days, 1 hour and 13 minutes ago"
sebagai gantinya, sehingga memperhitungkan semuanya!jika bAllowSegments adalah 2 ia akan kembali
"3 years and 2 months"
dan jika 6 (nilai maksimum) akan kembali"3 years, 2 months, 13 days, 13 hours, 29 minutes and 9 seconds"
, tetapi, diingatkan bahwa itu akan menjadiNEVER RETURN
sesuatu seperti ini"0 years, 0 months, 0 days, 3 hours, 2 minutes and 13 seconds ago"
karena memahami tidak ada data tanggal di 3 segmen teratas dan mengabaikannya, bahkan jika Anda menentukan 6 segmen , jadi jangan khawatir :). Tentu saja, jika ada segmen dengan 0 di dalamnya, itu akan memperhitungkannya saat membentuk string, dan akan ditampilkan sebagai"3 days and 4 seconds ago"
dan mengabaikan bagian "0 jam"! Nikmati dan berikan komentar jika Anda mau.Tentu saja, Anda akan memerlukan fungsi "ReplaceLast", yang mengambil string sumber, dan argumen yang menentukan apa yang perlu diganti, dan argumen lain yang menentukan dengan apa Anda ingin menggantinya, dan itu hanya menggantikan kejadian terakhir dari string itu. ... saya telah memasukkan yang saya miliki jika Anda tidak memilikinya atau tidak ingin mengimplementasikannya, jadi ini dia, itu akan berfungsi "sebagaimana adanya" tanpa modifikasi yang diperlukan. Saya tahu fungsi reverseit tidak lagi diperlukan (ada di .net) tetapi fungsi ReplaceLast dan ReverseIt dijalankan dari hari-hari pra-.net, jadi mohon maafkan bagaimana tanggalnya kelihatannya (masih berfungsi 100% tho, telah menggunakan em selama lebih dari sepuluh tahun, dapat menjamin mereka bebas bug) ... :). Bersulang.
sumber
Jika Anda menginginkan angka pastinya, Anda tidak bisa hanya dari Timespan, karena Anda perlu tahu bulan apa yang Anda hadapi, dan apakah Anda berurusan dengan tahun kabisat, seperti yang Anda katakan.
Baik pergi untuk perkiraan angka, atau melakukan beberapa kegelisahan dengan DateTimes asli
sumber
http://www.astro.uu.nl/~strous/AA/en/reken/juliaansedag.html
Jika Anda bisa mengubah waktu dari Tanggal Gregorian menjadi angka hari Julian , Anda bisa membuat operator untuk melakukan perbandingan angka hari zulian, yang bisa diketik dua kali untuk mendapatkan bulan, hari, detik, dll. Periksa yang di atas tautan untuk algoritme untuk mengonversi dari Gregorian ke Julian.
sumber
Tidak ada cara dibangun untuk melakukan ini secara akurat dalam idiomatic-c #. Ada beberapa solusi, seperti contoh CodeProject ini yang telah dikodekan oleh orang.
sumber
Jika Anda berurusan dengan bulan dan tahun, Anda perlu sesuatu yang tahu berapa hari yang dimiliki setiap bulan dan tahun mana yang lebih cepat.
Masukkan Kalender Gregorian (dan implementasi Kalender khusus budaya lainnya ).
Meskipun Kalender tidak menyediakan metode untuk secara langsung menghitung perbedaan antara dua titik dalam waktu, itu memang memiliki metode seperti
sumber
sumber
Metode mengembalikan daftar yang berisi 3 elemen pertama adalah tahun, kedua adalah bulan dan elemen akhir adalah hari:
sumber
Inilah kontribusi saya untuk mendapatkan perbedaan dalam Bulan yang menurut saya akurat:
Pemakaian:
Anda dapat membuat metode lain yang disebut DiffYears dan menerapkan logika yang persis sama seperti di atas dan AddYears daripada AddMonths di loop sementara.
sumber
Jauh terlambat ke permainan tapi saya membayangkan ini mungkin bermanfaat bagi seseorang. Mayoritas orang cenderung mengukur bulan ke bulan berdasarkan tanggal, tidak termasuk fakta bahwa bulan datang dalam variasi yang berbeda. Dengan menggunakan kerangka pemikiran itu, saya membuat satu garis yang membandingkan tanggal untuk kami. Menggunakan proses berikut.
Jika akhir tahun tidak lebih besar kami melakukan yang sama dengan 2A / 2B, tetapi tanpa menambahkan 12 bulan karena kami tidak perlu mengevaluasi sekitar tahun.
sumber
Pendapat saya tentang jawaban ini juga menggunakan metode ekstensi , tetapi dapat mengembalikan hasil positif atau negatif.
Beberapa tes:
sumber
Menggabungkan dua jawaban di atas, metode ekstensi lain adalah:
Terima kasih kepada @AdamRobinson dan @MarkWhittaker
sumber
Hitung tidak ada bulan antara 2 tanggal:
sumber