How to get last midnight in Dart? - datetime

I guess this is pretty common task in most languages, however it was not clear to me how to get this done in my Flutter app. How to retrieve DateTime object of the last midnight in Dart? Or potentially, any particular time today / tomorrow / yesterday?

This should do the same
var now = DateTime.now();
var lastMidnight = DateTime(now.year, now.month, now.day);
You can use this way to get different times of this day
var tomorrowNoon = DateTime(now.year, now.month, now.day + 1, 12);
var yesterdaySixThirty = DateTime(now.year, now.month, now.day - 1, 6, 30);
Depending on what you want can absolute values be more safe because adding/subtracting Duration can result in surprises because of leap years and daylight saving time.

Try this package Jiffy, uses the simplicity of momentjs syntax. See below
To get last midnight
var lastMidnight = Jiffy().subtract(days: 1).startOf(Units.DAY);
print(lastMidnight.dateTime); // 2019-10-20 00:00:00.000
//or you can also format it
print(lastMidnight.yMMMMEEEEdjm); // Sunday, October 20, 2019 12:00 AM

EDIT: Use this solution only if you are working with UTC (daylight saving times might mess it up), or rather use the accepted answer anyway.
The simplest solution I found so far:
final now = DateTime.now();
final lastMidnight = now.subtract(Duration(
hours: now.hour,
minutes: now.minute,
seconds: now.second,
milliseconds: now.millisecond,
microseconds: now.microsecond,
));
Then we can get any other time or day relative to today by subtracting or adding Duration, e.g.:
final tomorrowNoon = lastMidnight.add(Duration(days: 1, hours: 12));
final yesterdaySixThirty = lastMidnight
.subtract(Duration(days: 1))
.add(Duration(hours: 6, minutes: 30));
Note that DateTime is immutable and both methods (add, subtract) return a new object.

Related

DateTime in UTC not converting to Local

I'm receiving a DateTime response from API that's sets the timezone to UTC.
But when I try to convert the received data using toLocal() it doesn't convert.
my local time is HKT
here's my code.
//TIME DIFFERENCE
getNotificationDate(DateTime date) {
date = date.toUtc();
final convertedDate = date.toLocal();
final dateNow = DateTime.now();
print('TIMENOW: ' + dateNow.toString());
print('TIMENOTIFC: ' + convertedDate.toString());
final difference = dateNow.difference(convertedDate);
print('DIFFERENCE: ' + difference.toString());
return getDurationFormat(difference);
}
EDIT:
date is the DateTime I'm receiving from the API. which is in UTC timezone.
I used print('TIMEZONENAME: ' + date.timeZoneName; and it automatically sets the timezone to HKT. that's why it does nothing when I try to use date.toLocal()
Flutter gave us the easiest way to convert it.
You just need to pass utc: true while parsing your date.
var dateTime = DateFormat("yyyy-MM-dd HH:mm:ss").parse(dateUtc, true);
var dateLocal = dateTime.toLocal();
Input:
Assume my TimeZone : +05:30
UTC Date -> 2020-02-12 23:57:02.000
Output:
Local Date -> 2020-02-12 18:27:02.019660
// you have time in utc
var dateUtc = DateTime.now().toUtc();
print("dateUtc: $dateUtc"); // 2019-10-10 12:05:01
// convert it to local
var dateLocal = dateUtc.toLocal();
print("local: $dateLocal"); // 2019-10-10 14:05:01
Can you see the difference in hours, in utc it is 12 and locally it is 14.
Firstly, convert your Sting to DateTime.
> DateTime dateTime = DateTime.parse(json['pickUpTime']);
Secondly, add timeZoneOffSet to your converted date time it will convert utc to your local time.
> dateTime = dateTime.add(DateTime.parse(json['pickUpTime']).timeZoneOffset);
Final Code
DateTime dateTime = DateTime.parse(json['pickUpTime']);
dateTime = dateTime.add(DateTime.parse(json['pickUpTime']).timeZoneOffset);
You can try this code:
getNotificationDate(DateTime date) {
date = DateTime.utc(date.year,date.month,date.day,date.hour,date.minute,date.second);;
final convertedDate = date.toLocal();
final dateNow = DateTime.now();
print('TIMENOW: ' + dateNow.toString());
print('TIMENOTIFC: ' + convertedDate.toString());
final difference = dateNow.difference(convertedDate);
print('DIFFERENCE: ' + difference.toString());
return getDurationFormat(difference);
}
I've done something like this.
String dateTimeFormatter(String dateTime, {String? format}) {
return DateFormat(format ?? 'yyyy/MM/dd, hh:mm a')
.format(DateTime.parse(dateTime).toLocal())
.toString();
}
just pass the format which you want to display in your app.
If somebody needs to parse a UTC timestamp in isoformat, for example something like this:
>>> from datetime import datetime
>>> datetime.utcnow().format()
'2021-07-20T19:35:19.769891'
Then you can parse this and convert this to local time by
DateTime parseDatetimeFromUtc({required String isoFormattedString}){
var dateTime = DateTime.parse(isoFormattedString + '+00:00');
return dateTime.toLocal();
}
The '+00:00' is append here as the timezone information part which I do not send over my API to save some bytes. Maybe this helps someone who is in the same situation.
Of course you do not need this hardcoded suffix if you use a timezone aware timestamp in your backend:
>>> from datetime import datetime, timezone
>>> datetime.now(timezone.utc).isoformat()
'2021-07-20T19:42:36.538195+00:00'
For those who parsing TimeStamp from Firestore.
*sentAt is Timestamp
String timeToDate = widget.sentAt.toDate().toString();
var dateTime = DateFormat("yyyy-MM-dd HH:mm:ss").parse(timeToDate, true);
var dateLocal = dateTime.toLocal();
this is how i converted to my required time .which was showing as
I/flutter ( 5709): 16 Apr 08:30 PM 2021
when using the
var date=DateFormat("dd MMM hh:mm a y").format(DateTime.fromMillisecondsSinceEpoch(start*1000));
print(date);
but after using this code i got my right time
var date=DateFormat("dd MMM hh:mm a y").format(DateTime.fromMillisecondsSinceEpoch(start*1000).toUtc());
print(date);
which is
I/flutter ( 5709): 16 Apr 03:00 PM 2021
I tried several examples and forums, but it kept getting me the incorrect date time for my zone, The only way I made it work correctly was by using the GMT package
var nowLocal = DateTime.now();
print("toUtc: ${nowLocal.toUtc()}");
print("toLocalDateTime ${nowLocal.toLocalDateTime()}");
print("toLocal ${nowLocal.toLocal()}");
print("toIso8601String ${nowLocal.toIso8601String()}");
final timeZoneOffsetInHours = DateTime.now().timeZoneOffset.inHours;
final nowGMT = await GMT.now();
print("GMT: $nowGMT");
final nowActual = nowGMT?.add(Duration(hours: timeZoneOffsetInHours));
print("nowActual $nowActual");
Two solutions I implemented
var date = DateFormat("yyyy-MM-ddTHH:mm:ss").parse(json, true);
var dateLocal = date.toLocal();
Other solutions add "Z"
You need to indicate a timezone to DateTime.parse, otherwise it assumes local time. From the dartdoc:
var date = DateTime.parse("${dateString}Z").toLocal();
var dateFormat = date2.toLocal();
Install intl package from pub.dev
add following line :
import 'package:intl/intl.dart';
You can make an extension like below so it will be very helpful and easy to use anywhere in a whole project.
//just make sure you have passed the right date format of utc("yyyy-MM-dd HH:mm:ss"). I have passed by default my format.
//for example
// 2020-11-25 24:12:36 -> "yyyy-MM-dd HH:mm:ss"
DateTime localDate=utcDateTime.toLocalDateTime();
//for different formats you can pass your own dateFormat for utcDate like below:
// 20-11-25 24:12:36 -> "yy-MM-dd HH:mm:ss"
DateTime localDate=utcDateTime.toLocalDateTime("yy-MM-dd HH:mm:ss");
extension DateTimeExtension on DateTime {
DateTime toLocalDateTime({String format = "yyyy-MM-dd HH:mm:ss"}) {
var dateTime = DateFormat(format).parse(this.toString(), true);
return dateTime.toLocal();
}
}
convert utc number to DateTime:
DateTime utcToDateTime(int utc) {
return DateTime(1970, 1, 1).add(Duration(seconds: utc));
}
//test
DateTime d = utcToDateTime(1649297709);
print(d);

Get the next upcoming Friday at 5 PM

I need to display how far away a deadline is that is every Friday at 5PM. Moment will give me that date for a day of the week, but it's always the current time, so the deadline always displays 'x days, 23 hours, 59 minutes'. How do I get the day, AND a specific time from moment? In my example, I need deadline to be 'next Friday, at 17:00' instead of 'next Friday, at the current time'
console.log(timeLeft());
function timeLeft() {
var dayINeed = 5; // for Friday
var deadline;
// if we haven't yet passed the day of the week that I need:
if (moment().isoWeekday() <= dayINeed) {
// then just give me this week's instance of that day
deadline = moment().isoWeekday(dayINeed);
} else {
// otherwise, give me next week's instance of that day
deadline = moment().add(1, 'weeks').isoWeekday(dayINeed);
}
console.log(deadline);
const now = moment();
const days = deadline.diff(now, 'days');
const hours = deadline.subtract(days, 'days').diff(now, 'hours');
const minutes = deadline.subtract(hours, 'hours').diff(now, 'minutes');
return `${days} days, ${hours} hours, and ${minutes} minutes`;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.js"></script>
You have to set to deadline the time (17:00), instead of getting current time, you can use moment startOf() and set(), simply add the following to your code:
deadline.startOf('day').set({h: 17});
This way you are setting 17:00:00 to deadline and you will get the desired output.
Here a full example:
console.log(timeLeft());
function timeLeft() {
var dayINeed = 5; // for Friday
var deadline;
// if we haven't yet passed the day of the week that I need:
if (moment().isoWeekday() <= dayINeed) {
// then just give me this week's instance of that day
deadline = moment().isoWeekday(dayINeed);
} else {
// otherwise, give me next week's instance of that day
deadline = moment().add(1, 'weeks').isoWeekday(dayINeed);
}
deadline.startOf('day').set({h: 17});
console.log(deadline.format());
const now = moment();
const days = deadline.diff(now, 'days');
const hours = deadline.subtract(days, 'days').diff(now, 'hours');
const minutes = deadline.subtract(hours, 'hours').diff(now, 'minutes');
return `${days} days, ${hours} hours, and ${minutes} minutes`;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.js"></script>
If you want, you can use setter like hour(), minute() etc to set 17:00:00 to deadline.

Meteor : Countdown timer

This might be a big ask, but I'm completely stuck so any help is appreciated.
I'm trying to create a countdown timer that runs from Sunday to Sunday and just restarts at the end of the week. I've tried using countdown packages in atmosphere but the documentation is limited and never seems to work. I've also tried to download and run 3rd party jquery packages however they always seem to crash meteor.
Could someone point me in the right direction or show me how to do this in meteor?
Specific details:
Countdown timer used to run an auction.
Auction runs for 7 days, Starts Sunday at 12:00am finishes 7 days
later.
Auction resets and starts again after 7 days.
Countdown timer will be visible by users on multiple pages.
Countdown timer units to be displayed - Days, Hours, Minutes, Seconds (eg.
6 days, 3 hours, 55 minutes, 22 seconds until the next auction
begins.)
The question is too large. But i can suggest the small step to work with this. Your auction scheme will need to have a endDateTime to store the value (even it will start/end in Sunday). On the template you need to display the timer, set one ReactiveVar as number (to count down), one ReactiveVar as string (to display to result)
Template['countDownTemplate'].created = function() {
var due, dueDate, duration, now, num, self;
self = this;
dueDate = Template.instance().data['auction']['endDateTime'];
now = moment.utc();
due = moment.utc(dueDate, 'YYYY-MM-DD hh:mm:ss');
duration = moment.duration(due.diff(now));
num = Math.floor(duration.asSeconds());
if (num >= 0) {
self['remaining'] = new ReactiveVar<number>(num);
self['timeRemaining'] = new ReactiveVar<string>(convertPeriod(num));
self['interval'] = Meteor.setInterval((function() {
var remaining;
remaining = self['remaining'].get();
self['remaining'].set(remaining - 1);
self['timeRemaining'].set(convertPeriod(self['remaining'].get()));
if (remaining === 0) {
Meteor.clearInterval(self['interval']);
} else {
remaining = Math.floor(moment.duration(due.diff(now)).asSeconds());
}
}), 1000);
}
};
(the convertPeriod will be based on the remaining number to convert into your correct format)
The rest is just about showing timeRemaining in the correct format with the convertPeriod

node RRule check if rule day is today

I am using 'rrule.js' library in node to parse my RRule. I would like to know if current day is same as rule day. It works on most cases but not all. I also use moment.js to compare. The issue is in "rule.after()". It should include the current day but it doesn't.
function checkIfToday(rruleStr){
var RRule = require('rrule').RRule;
var moment = require('moment');
var rule = RRule.fromString(rruleStr);
// Convert all dates into UTC before comparison
var todayutc = moment().utc(); // today in UTC
var nextOccurrence = rule.after(todayutc,inc=true); // next rule date including today
var nextOccurutc = moment(nextOccurrence).utc(); // convert today into utc
var match = moment(nextOccurutc).isSame(todayutc, 'day'); // check if 'DAY' is same
return match;
}
Any idea what's the best way to do this.
Thanks.
This worked for me. Try setting the time of todayutc back to the beginning of the day using moment's startOf method:
function checkIfToday(rruleStr){
var RRule = require('rrule').RRule;
var moment = require('moment');
var rule = RRule.fromString(rruleStr);
// Convert all dates into UTC before comparison
var todayutc = moment().utc().startOf('day'); // today in UTC
var nextOccurrence = rule.after(todayutc, true); // next rule date including today
var nextOccurutc = moment(nextOccurrence).utc(); // convert today into utc
var match = moment(nextOccurutc).isSame(todayutc, 'day'); // check if 'DAY' is same
return match;
}

How to compare two dates with each other in Flex?

I have a standard ISO8601 date string:
2004-02-12T15:19:21+00:00
I want to know if this date is older than 10 minutes ago in Flex. So basically:
if ("2004-02-12T15:19:21+00:00" > current_time - 10mins) {
// do whatever
}
What would the syntax be in Flex? I'm basically stuck at trying to convert the string into a Flex Date Object without parsing it character by character.
If you don;t care about the timezone i.e. the date string is in the same timezone as where you are running the application then this should work.
var date:Date = DateFormatter.parseDateString("2004-02-12T15:19:21+00:00");
var now:Date = new Date();
var tenMinAgo:Number = now.time - 1000*60*10;
if (date.time < tenMinAgo) {
trace("More than 10 min ago");
}

Resources