How to get the difference between two chrono dates? - date

I'd like to get a "time-span" difference between today 08/11/2020 and 01/01/1970 in such format:
Timespan:
50 year(s) 10 month(s) 7 day(s)
The code below correctly calculates this for: today - 01/01/1970. However, it fails miserably for input like 23/12/1970 giving:
50 year(s) -1 month(s) -15 day(s)
Whereas the expected result is 49 year(s) 10 month(s) 16 day(s).
More dates to test:
09/01/1985
Got: 35 year(s) 10 month(s) -1 day(s) but expected 35 year(s) 9 month(s) 30 day(s).
24/02/1936
Got: 84 year(s) 9 month(s) -16 day(s) but expected 84 year(s) 8 month(s) 15 day(s).
Cargo.toml:
[package]
name = "relative-delta"
version = "0.1.0"
authors = ["baduker"]
edition = "2018"
[dependencies]
chrono = "0.4.19"
Code:
use chrono::{NaiveDateTime, DateTime, Utc, Datelike};
fn main() {
let date_string = "23/12/1970";
let naive_date = chrono::NaiveDate::parse_from_str(date_string, "%d/%m/%Y").unwrap();
let naive_datetime: NaiveDateTime = naive_date.and_hms(0, 0, 0);
let date = DateTime::<Utc>::from_utc(naive_datetime, Utc);
let years = Utc::now().year() - date.year();
let months = Utc::now().month() as i64 - date.month() as i64;
let days = Utc::now().day() as i64 - date.day() as i64;
println!("Timespan:\n{} year(s) {} month(s) {} day(s)", years, months, days);
}

Your calculation does not make sense to me e.g. if today's date is 1st Nov 2021, your calculation would return 1 - 23 = -22 as the number of days. Today is my third day of learning Rust and therefore I do not have enough expertise to give you an optimized solution. However, if you assume a year of 365 days and a month of 30 days, the following solution should meet your requirement.
use chrono::{DateTime, Utc};
fn main() {
// Tests
print_diff("23/12/1970");
}
fn print_diff(date_string: &str) {
let today = Utc::now();
let datetime =
DateTime::<Utc>::from_utc(chrono::NaiveDate::parse_from_str(date_string, "%d/%m/%Y")
.unwrap()
.and_hms(0, 0, 0), Utc);
let diff = today.signed_duration_since(datetime);
let days = diff.num_days();
let years = days / 365;
let remaining_days = days % 365;
let months = remaining_days / 30;
let days = remaining_days % 30;
println!("{} years {} months {} days", years, months, days);
}
Output:
50 years 11 months 9 days
Playground

Related

Flutter hours and minute count issue

I need to sum the hours and minutes so I am doing this like ill convert hours in second and minutes in second then sum it
var totalServiceSeconds = minsSeconds + hoursSeconds;
var c = Duration(seconds: totalServiceSeconds);
print('c ${c.toString()}');
it's showing c 25:05:00.000000 which is correct
Know I need to show this as hours and minutes in the text widget. So I am converting to DateTime like this
var format = DateFormat("HH:mm");
DateTime totalServiceTime = format.parse(c.toString());
But it's printing it like this totalServiceTime 1970-01-02 01:05:00.000
This issue is only when the hours are 24 or more. If my hours are 24 then it's showing 0 and if greater than 24 then it's showing 1 2 so on. I know it because it's considering 24 as 0 but what can I do about this?
I want to show 24 if it's 24 hours or if greater than 24 like 26 need to show 26.
You do not want to convert it into a DateFormat because time steps of 24 hours is how they count a full day. Instead you should format var c as shown below
var totalServiceSeconds = minsSeconds + hoursSeconds;
var c = Duration(seconds: totalServiceSeconds);
print('c ${c.toString()}');
String FormatDuration = "${c.inHours}:${c.inMinutes.remainder(60)}:${(c.inSeconds.remainder(60))}";
print(FormatDuration);
String FormatDuration2 = "${c.inHours} hours ${c.inMinutes.remainder(60)} minutes ${(c.inSeconds.remainder(60))} seconds";
print(FormatDuration2);
The output will then be
c 25:05:00.000000 <-------previous
25:5:0 <-------new option 1
25 hours 5 minutes 0 seconds <-------new option 2

Swift Number Of Weeks in Month

I'm using Swift 5. I'm trying to get the number of weeks in a month. Jan 2021 prints 6 weeks, but May prints 5 weeks. I'm thinking the problem is firstWeekday is set to 1. Is there a way to get the number of weeks in a given month without setting firstWeekday?
var localCalendar = Calendar.current
localCalendar.firstWeekday = 1
let weekRange = localCalendar.range(of: .weekOfMonth, in: .month, for: dateFormatter.date(from: monthName)!)
if let weekRange = weekRange {
print("\(monthName) has \(weekRange.count) weeks.")
}
It seems you do not want the number of weeks in a month at all. You want the number of rows in a calendar printout.
The formula for the number of rows needed to represent a month on a standard Gregorian-style calendar is as follows.
Start with the number of days in the month. Add to that the number of blank days before the start of the month, beginning with Sunday. For example, January 2021 is 31 + 5 = 36, because it's 31 days long but 5 days (Sunday thru Thursday) are not part of it before the start. To put it another way: the first day of January 2021 is a Friday; that is day 5 of the week if we call Sunday day 0, so we get 31 + 5.
Now integer-divide by 7. We need at least that number of rows. So (31+5)/7 using integer division is 5. The question is: is that all the rows we need?
To find out, get the remainder of that division. If it is not zero, add another row. So (31+5)%7 is 1, which tells us that one more day needs to be accommodated so we need another row. That makes 6.
Thus:
// `startingOn` pretends that Sunday is day 0
func rowsNeededForMonthWith(numberOfDays n: Int, startingOn i: Int) -> Int {
let (quot,rem) = (n+i).quotientAndRemainder(dividingBy: 7)
return quot + (rem == 0 ? 0 : 1)
}
Here are some quick sanity tests:
// January 2021
rowsNeededForMonthWith(numberOfDays: 31, startingOn: 5) // 6
// But suppose it had 30 days?
rowsNeededForMonthWith(numberOfDays: 30, startingOn: 5) // 5
// Or suppose it had started on Thursday? (cf July 2021)
rowsNeededForMonthWith(numberOfDays: 31, startingOn: 4) // 5

How can I create a DateInteveral to represent 1 day 2 hr 10 min 5 sec

From DateInteveral init(), I need to specify 2 dates and it will calculate the time difference between the 2 days. https://cocoacasts.com/working-with-nsdateinterval-in-swift
My question is how can I create DateInteveral for a specify Inteveral say 1 day 2 hr 10 min 5 sec? I see there is another class TimeInterval, but the unit is in seconds. Is convert back an d forth my interval into (1 day 2 hr 10 min 5 sec) to sec and save it in TimeInterval my only option?
You can use calendar method date(byAdding:to:wrappingComponents:) to add the desired DateComponents that represents that time interval to your DateInterval start date:
let start = Date()
let dateComponents = DateComponents(day: 1, hour: 2, minute: 10, second: 5)
let end = Calendar.current.date(byAdding: dateComponents, to: start)!
let dateInterval = DateInterval(start: start, end: end)
let dcf = DateComponentsFormatter()
dcf.allowedUnits = [.second, .minute, .hour, .day]
dcf.maximumUnitCount = 4
dcf.unitsStyle = .full
dcf.string(from: dateInterval.duration) // "1 day, 2 hours, 10 minutes, 5 seconds"

Coldfusion date difference in days and hours

I'm having a problem with Coldfusion's DateDiff(). I'm trying to get the difference between two dates with times, like the following examples:
fromdate=06/11/2017 22:10
todate =16/11/2017 23:20
should return:
10 days, 1 hour and 10 minutes
fromdate=06/11/2017 22:10
todate =16/11/2017 20:20
should return:
9 days, 22 hours, 10 minutes
Any help?
Code:
<cfset dtFrom = "11/06/2017 22:10" />
<cfset dtTo = "11/16/2017 23:20" />
<cfoutput>
#DateDiff( "d", dtFrom, dtTo)# Days,
#DateDiff( "h", dtFrom, dtTo) % 24# Hours
#DateDiff( "n", dtFrom, dtTo) % 24 % 60# Minutes
</cfoutput>
In addition to the previous suggestion, DateDiff() isn't going to understand those specific strings or that "06/11/2017" should mean November 6. The result will be:
158 days 1 hours 10 minutes
For it to work as expected, you must convert the strings into date objects first. For example use LSParseDateTime with the right Locale.
fromDate = lsParseDateTime("06/11/2017 22:10", "English (UK)", "dd/MM/yyyy hh:mm");
toDate = lsParseDateTime("16/11/2017 23:20", "English (UK)", "dd/MM/yyyy hh:mm");
or possibly:
fromDate = lsParseDateTime("06/11/2017 22:10", "English (UK)");
toDate = lsParseDateTime("16/11/2017 23:20", "English (UK)");
Here is one way.
totalMinutes = datediff("n", fromDate, toDate);
days = int(totalMinutes /(24 * 60)) ;
minutesRemaining = totalMinutes - (days * 24 * 60);
hours = int(minutesRemaining / 60);
minutes = minutesRemaining mod 60;
writeoutput(days & ' days ' & hours & ' hours ' & minutes & ' minutes');

NSDate timeIntervalSinceDate calculates incorrectly by 60 minutes

Trying to figure out why the following code results in 90,000 which is exactly 1 hour over a day. The created dates are both set to noon of consecutive days so the answer should be 86,400 (24*60*60).
let currentCalendar = NSCalendar.currentCalendar();
let components1 = NSDateComponents()
components1.year = 2015
components1.month = 11
components1.day = 1
components1.hour = 12
components1.minute = 0
components1.second = 0
let myDate1 = currentCalendar.dateFromComponents(components1)!
let components2 = NSDateComponents()
components2.year = 2015
components2.month = 10
components2.day = 31
components2.hour = 12
components2.minute = 0
components2.second = 0
let myDate2 = currentCalendar.dateFromComponents(components2)!
let difference = myDate1.timeIntervalSinceDate(myDate2)
Running swift 2 (Xcode 7.0)
Daylight savings time ends on Nov 1, 2015. The 25-hour difference is correct. There will also be a 23-hour day in the spring when DST begins.
This is why, if you want to be sure to get the same clock time on another date, you can’t just add or subtract multiples of 24 hours.
This only goes for places that observe DST, which is probably why some commenters on the original question are seeing a 24-hour difference in their local time zone.