Dart: inconsistency in adding days to dates - dart

When adding one day to 2020-09-18 I get 2020-09-19 00:00:00.000 but when I add 3 days (or more) I get 2020-09-20 23:00:00.000 which first why I got 23 hour? second adding 3 days to 18 is 21 not 20!
What is the problem?
void main() {
var dateOne = DateTime.parse('2020-09-18 00:00:00.000');
var dateTwo = dateOne.add(Duration(days: 1 )); // 2020-09-19 00:00:00.000
var dateThree = dateOne.add(Duration(days: 3 )); // 2020-09-20 23:00:00.000
print(dateTwo);
print(dateThree);
}

The reason for this is Daylight Saving Time since the add method does only understand seconds as documented in the API and the Duration are therefore converted to seconds before it is used:
Notice that the duration being added is actually 50 * 24 * 60 * 60 seconds. If the resulting DateTime has a different daylight saving offset than this, then the result won't have the same time-of-day as this, and may not even hit the calendar date 50 days later.
Be careful when working with dates in local time.
https://api.dart.dev/stable/2.7.2/dart-core/DateTime/add.html
As you also have mentioned yourself, you can get around the issue by using UTC instead.

Related

How to More Elegantly Calculate Epoch Time for Next Sunday at Midnight in Dart?

When a user opens my app, there's a countdown timer that shows how much time left until Sunday at midnight (which is when the week's contest would end).
To get the initial value used in the countdown, my code adds 604800000 (which is the amount of milliseconds in a week) in a loop to a starting value of 1595203200000 (which the milliseconds since epoch of an arbitrary past Sunday at midnight) until it's greater than now:
int now = DateTime.now().millisecondsSinceEpoch;
int nextSundayAtMidnight = 1595203200000; // starting value is from arbitrary past Sunday at midnight
while (now > nextSundayAtMidnight) {
print('now is still greater than nextSundayAtMidnight so adding another 604800000 until it\'s not');
nextSundayAtMidnight += 604800000;
}
print('nextSundayAtMidnight is $nextSundayAtMidnight');
It works, but it seems like there should be a better way that's based on DateTime.now without having to manually specify that arbitrary starting value. Is there?
What's the syntax in dart to do this more elegantly?
Thanks in advance!
The following code uses addition of the difference in weekdays to get the date of the upcoming Sunday and then shifts the exact DateTime to being at 11:59:59 pm. There are comments in the code that describe what each line does.
It uses the many helpful methods already provided in the DateTime class in dart.
void main()
{
var now = DateTime.now();
//Obtains a time on the date of next sunday
var nextSunday = now.add(Duration(days: DateTime.sunday - now.weekday));
//Shifts the time to being 11:59:59 pm on that sunday
var nextSundayMidnight = DateTime(nextSunday.year, nextSunday.month, nextSunday.day + 1).subtract(Duration(seconds: 1));
//Gets the difference in the time of sunday at midnight and now
var timeToSundayMidnight = nextSundayMidnight.difference(now);
print(timeToSundayMidnight);
}

How can I check if a date / time is within 1 minute of the current date / time

I have an access token with an expiration time. I would like to check when using my access token, does it expire within a minute.
If it does expire in less than a minute, I would like to take some action.
I am struggling to understand how I can check the date and time against the current date / time.
The exp time on my token looks like 1549103089 but using my auth lib 'AeroGearOAuth2' I can access it and print it out as 2019-02-02 10:13:48 +0000
I assume the number 1549103089 is stored in an Int or Double variable.
1549103089 represents the number of seconds since 1970/01/01 00:00:00 UTC. Therefore, you can get the current date as the number of seconds since 1970, then subtract the current date from 1549103089. If the number is less than 60 but greater than 0, it means the current date is within one minute before the expiration date.
let expirationDate: Double = 1549103089
let currentDate = Date().timeIntervalSince1970
if (0.0...60).contains(expirationDate - currentDate) {
// within one minute!
}

Aggregate 15 minute time slots to 30 minutes time slots

I have a list of time slots with a 15 minute interval.
Each slot can have a activity bound to it that makes the slot "reserved".
What is the best way to return the slots in groups of 30 minutes.
So basically, how can I go from this:
10:00
10:15 = this is a reserved slot
10:30
To this:
10:00
10:30
This whole slot is then reserved because it contains the reserved 10:15 slot.
Without changing the slot size itself.
Is this possible to do within the linq query itself or do I have to return the collection of 15 minute slots and apply the 30 minute logic afterwards?
Please point me in the right direction, thanks!
The slots are object with these properties and types:
TimeslotId (int)
SlotStart (DateTime)
ActivityId (int)
UPDATE:
Ok, I tried to group the slots with this query.
var groups = service.TestGrouping().GroupBy(x =>
{
var stamp = x.SlotStart;
stamp = stamp.AddMinutes(-(stamp.Minute % 30));
stamp = stamp.AddMilliseconds(-stamp.Millisecond - 1000 * stamp.Second);
return stamp;
}).Select(g => new Sample() { GroupTime = g.Key, GroupedSlots = g.ToList() }).ToList();
Which takes me a little closer. Now I get the slots aggregated to closest 30 minute, like 8:00-8:30, 8:30-9:00.
However, this does not work for slots that is within quarter to / quarter past. I need some logic to catch all possible half hours:
8:00-8:30, 8:15-8:45, 8:30-9:00, 8:45-9:15.
How would the logic look like?

joda overlap method for ambiguous hour

I'm trying to find out if there is any overlap between two joda intervals. value of the variables are given below. I'm not sure why the overlap is being returned as 'null'.
final Interval overlap = range.overlap(new Interval(beginDateTime, endDateTime));
beginDateTime = 2013-11-03T00:07:00.000Z
endDateTime = 2013-11-03T00:08:00.000Z
range = 2013-11-03T00:00:00.000-05:00/2013-11-03T23:59:59.999-06:00
Interval created by 'beginDateTime' and 'endDateTime' corresponds to ambiguous hour in America/Chicago time zone. Variable 'range' represents November 3rd in America/Chicago time zone.
I tried to debug into Interval.class, could not find out the reason.
thanks.
Never mind, found the issue.
beginDateTime and endDateTime be 2013-11-03T07:00:00.000Z and 2013-11-03T08:00:00.000Z respectively.
My test data was incorrect as listed in the question (that is not ambiguous hour, it is interval of just 1 minute, I swapped minutes with hour values) :)

Calculating how many 'Midnights' is one date past another in PHP?

I have a start/end times for a calculation I'm trying to do and am having a problem seeing if the end time is before 12AM the day after the start time. Also, I need to calculate how many days past the start time it is.
What I have: Start Date, End Date
What I need:
- How many 'Midnights' is the End Date past the Start Date?
Has anyone done anything like this?
This uses PHP 5.3, if you have an earlier version you may need to use unix timestamps to figure out the difference. The number of midnights should be the number of days difference assuming both start and end times have the same time. So setting both to be midnight of their current day setTime(0,0), should make the calculation correct.
Using the DateTime objects.
$start = new DateTime('2011-03-07 12:23:45');
$end = new DateTime('2011-03-08 1:23:45');
$start->setTime(0,0);
$end->setTime(0,0);
$midnights = $start->diff($end)->days;
Without using the setTime() calls, this would result in 0, because there is less than 24 hours between start and end. With the setTime() this results in 1 because now the difference is exactly 24 hours.
The diff() function was introduced in 5.3 along with the DateInterval class. In 5.2 you can still use the DateTime class but will have to work out the total days using the Unix timestamp.
$midnights = ($end->format('U') - $start->format('U')) / 86400
You can wrap that in an abs() function to the order of start/end does not matter.
Note: These functions may need to be tested for cases that involve DST.
A comment in the php date documentation uses round after dividing by 86400 (number of seconds in a day), to counter any issues that could be involved with DST.
An alternative approach with DateTimes would be to create them in the UTC.
$utcTimezone = new DateTimeZone('UTC');
$start = new DateTime('2011-03-07 12:23:45', $utcTimezone);
$end = new DateTime('2011-03-08 1:23:45', $utcTimezone);

Resources