I need to store and compare dates (without times) in my app, without caring about time zones.
I can see three solutions to this:
(date1.year == date2.year && date1.month == date2.month && date1.day == date2.day)
This is what I'm doing now, but it's horrible verbose.
date1.format("YYYYMMDD") == date2.format("YYYYMMDD")
This is still rather verbose (though not as bad), but just seems inefficient to me...
Create a new Date class myself, perhaps storing the date as a "YYYYMMDD" string, or number of days since Jan 1 1980. But this means re-implementing a whole bunch of complex logic like different month lengths, adding/subtracting and leap years.
Creating a new class also avoids an edge case I'm worried about, where adding Duration(days: 1) ends up with the same date due to daylight saving changes. But there are probably edge cases with this method I'm not thinking of...
Which is the best of these solutions, or is there an even better solution I haven't thought of?
Since I asked this, extension methods have been released in Dart. I would now implement option 1 as an extension method:
extension DateOnlyCompare on DateTime {
bool isSameDate(DateTime other) {
return year == other.year && month == other.month
&& day == other.day;
}
}
You can use compareTo:
var temp = DateTime.now().toUtc();
var d1 = DateTime.utc(temp.year,temp.month,temp.day);
var d2 = DateTime.utc(2018,10,25); //you can add today's date here
if(d2.compareTo(d1)==0){
print('true');
}else{
print('false');
}
DateTime dateTime = DateTime.now();
DateTime _pickedDate = // Some other DateTime instance
dateTime.difference(_pickedDate).inDays == 0 // <- this results to true or false
Because difference() method of DateTime return results as Duration() object, we can simply compare days only by converting Duration into days using inDays property
The easiest option is just to use DateUtils
For example
if (DateUtils.isSameDay(date1, date2){
print('same day')
}
isSameDay takes in 2 DateTime objects and ignores the time element
I am using this function to calculate the difference in days.
Comparing dates is tricky as the result depends not just on the timestamps but also the timezone of the user.
int diffInDays (DateTime date1, DateTime date2) {
return ((date1.difference(date2) - Duration(hours: date1.hour) + Duration(hours: date2.hour)).inHours / 24).round();
}
Use instead the package: dart_date
Dart Extensions for DartTime
dart_date provides the most comprehensive, yet simple and consistent toolset for manipulating Dart dates.
dart_date
DateTime now = DateTime.now();
DateTime date = ....;
if (date.isSameDay(now)) {
//....
} else {
//....
}
Also here the difference in days :
int differenceInDays(DateTime a, DateTime b) => a.differenceInDays(b);
Use isAtSameMomentAs:
var date1 = DateTime.now();
var date2 = date1.add(Duration(seconds: 1));
var isSame = date1.isAtSameMomentAs(date2); // false
Related
I have a scenario where user selects a start date and end date and user also selects a specific day I need to show that specific day with date that occurs between them.
I tried the Intl package difference method but did not work
You can use this method. Takes the start and end date and also the weekday. Note, can pass in 3 as an int or 'DateTime.wednesday' as the argument.
Note, idea based on mirkancal's answer in this thread
List<DateTime> getAllDatesOfAWeekday(
{required DateTime startDate,
required DateTime endDate,
required int weekday}) {
List<DateTime> allDates = [];
for (int i = 0; i <= endDate.difference(startDate).inDays; i++) {
if (startDate.add(Duration(days: i)).weekday == weekday) {
allDates.add(startDate.add(Duration(days: i)));
}
}
return allDates;
}
Guys. I want to write a simple code to add X weeks to a chosen Date but I just can't figure out how. I always get a ton of errors. The function should basically return the chosen date plus "addedweeks" in the format "dd-MM-yyyy". Below is my last attempt. Thanks in advance!
import 'dart:math' as math;
String? addXWeeks(
DateTime? datum,
int? addedweeks,
) {
// add 2 weeks
DateTime date = datum.toLocal;
date = DateTime(date.year, date.month, date.day + (addedweeks*7));
}
this is very easy. DateTime has a method called add. You only need to add 7 days, because duration has not the propertie "weeks".
Here is a samle:
void main() {
// Current date
DateTime date = DateTime.now();
// Weeks you want to add
int weeksToAdd = 10;
print("Before: $date");
// Multiply 7 (days a week) with your week and set int to and int
date = date.add(Duration(days: (7 * weeksToAdd).toInt()));
print("After: $date");
// Format date
print("Format date: ${date.day}.${date.month}.${date.year}");
}
The output:
Before: 2022-10-06 13:23:16.342888
After: 2022-12-15 12:23:16.342888
Format date: 15.12.2022
I will receive DateTime in UTC format from API and I need to convert the DateTime to local time zone based on the condition.
We have toLocal() method to change the time based on the device time zone.
condition: 23-4-2021 // no need to change it to toLocal()
23-4-2021 00:00:00 // no need to change it to toLocal()
23-4-2021 10:30:34 // need to change it to toLocal()
If we have time in the DateTime then only we have to change it in local time.
DateTime utcToDateTimeLocal(DateTime value) {
return value.toLocal();
}
Thanks!
Something like this maybe ?
DateTime utcToDateTimeLocal(DateTime value) {
if (value.hour!=0 || value.minute!=0 || value.second!=0){
return value.toLocal();
}
return value;
}
Here is quick solution that work for me.
You can get time (or any format) by DateFormat class
In your case
dateTime = '23-4-2021 10:30:34'
final format = DateFormat('HH:mm a');
final clockString = format.format(dateTime);
you will get // 10:30 AM
DateTime utcToDateTimeLocal(DateTime value) {
var dateFormat =
DateFormat("dd-mm-yyyy hh:mm a"); // you can change the format here
var utcDate =
dateFormat.format(DateTime.parse(value.toString())); // pass the UTC time here
var localDate = dateFormat.parse(utcDate, true).toLocal().toString();
return DateTime.parse(localDate);
}
I got a exception while implementing the following statements.
DateTime result;
if (!DateTime.TryParse(rule.data, out result))
return jobdescriptions;
if (result < new DateTime(1754, 1, 1)) // sql can't handle dates before 1-1-1753
return jobdescriptions;
return jobdescriptions.Where(j => j.JobDeadline.Date == Convert.ToDateTime(rule.data).Date );
Exception
The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
I know what the exception means but i don't know how to get rid of it. Any help?
You can use the TruncateTime method of the EntityFunctions to achieve a correct translations of the Date property into SQL:
using System.Data.Objects; // you need this namespace for EntityFunctions
// ...
DateTime ruleData = Convert.ToDateTime(rule.data).Date;
return jobdescriptions
.Where(j => EntityFunctions.TruncateTime(j.JobDeadline) == ruleData);
Update: EntityFunctionsis deprecated in EF6, Use DbFunctions.TruncateTime
LINQ to Entities cannot translate most .NET Date methods (including the casting you used) into SQL since there is no equivalent SQL.
The solution is to use the Date methods outside the LINQ statement and then pass in a value. It looks as if Convert.ToDateTime(rule.data).Date is causing the error.
Calling Date on a DateTime property also cannot be translated to SQL, so a workaround is to compare the .Year .Month and .Day properties which can be translated to LINQ since they are only integers.
var ruleDate = Convert.ToDateTime(rule.data).Date;
return jobdescriptions.Where(j => j.Deadline.Year == ruleDate.Year
&& j.Deadline.Month == ruleDate.Month
&& j.Deadline.Day == ruleDate.Day);
For EF6 use DbFunctions.TruncateTime(mydate) instead.
"EntityFunctions.TruncateTime" or "DbFunctions.TruncateTime" in ef6 Is Working but it has some performance issue in Big Data.
I think the best way is to act like this:
DateTime ruleDate = Convert.ToDateTime(rule.data);
DateTime startDate = SearchDate.Date;
DateTime endDate = SearchDate.Date.AddDay(1);
return jobdescriptions.Where(j.Deadline >= startDate
&& j.Deadline < endDate );
it is better than using parts of the date to. because query is run faster in large data.
Need to include using System.Data.Entity;. Works well even with ProjectTo<>
var ruleDate = rule.data.Date;
return jobdescriptions.Where(j => DbFunctions.TruncateTime(j.Deadline) == ruleDate);
What it means is that LINQ to SQL doesn't know how to turn the Date property into a SQL expression. This is because the Date property of the DateTime structure has no analog in SQL.
It worked for me.
DateTime dt = DateTime.Now.Date;
var ord = db.Orders.Where
(p => p.UserID == User && p.ValidityExpiry <= dt);
Source: Asp.net Forums
I have the same problem but I work with DateTime-Ranges.
My solution is to manipulate the start-time (with any date) to 00:00:00
and the end-time to 23:59:59
So I must no more convert my DateTime to Date, rather it stays DateTime.
If you have just one DateTime, you can also set the start-time (with any date) to 00:00:00 and the end-time to 23:59:59
Then you search as if it were a time span.
var from = this.setStartTime(yourDateTime);
var to = this.setEndTime(yourDateTime);
yourFilter = yourFilter.And(f => f.YourDateTime.Value >= from && f.YourDateTime.Value <= to);
Your can do it also with DateTime-Range:
var from = this.setStartTime(yourStartDateTime);
var to = this.setEndTime(yourEndDateTime);
yourFilter = yourFilter.And(f => f.YourDateTime.Value >= from && f.YourDateTime.Value <= to);
As has been pointed out by many here, using the TruncateTime function is slow.
Easiest option if you can is to use EF Core. It can do this. If you can't then a better alternative to truncate is to not change the queried field at all, but modify the bounds. If you are doing a normal 'between' type query where the lower and upper bounds are optional, the following will do the trick.
public Expression<Func<PurchaseOrder, bool>> GetDateFilter(DateTime? StartDate, DateTime? EndDate)
{
var dtMinDate = (StartDate ?? SqlDateTime.MinValue.Value).Date;
var dtMaxDate = (EndDate == null || EndDate.Value == SqlDateTime.MaxValue.Value) ? SqlDateTime.MaxValue.Value : EndDate.Value.Date.AddDays(1);
return x => x.PoDate != null && x.PoDate.Value >= dtMinDate && x.PoDate.Value < dtMaxDate;
}
Basically, rather than trimming PoDate back to just the Date part, we increment the upper query bound and user < instead of <=
I have the below function
public static List<DateTime> GetOnlyFridays(DateTime endDate, int weeks, bool isIncludeBaseDate)
{
//Get only the fridays from the date range
List<DateTime> dtlist = new List<DateTime>();
List<DateTime> tempDtlist = (from dtFridays in GetDates(endDate, weeks)
where dtFridays.DayOfWeek == DayOfWeek.Friday
select dtFridays).ToList();
if (isIncludeBaseDate)
{
dtlist = tempDtlist.Skip(1).ToList();
dtlist.Add(endDate);
}
else
{
dtlist = tempDtlist;
}
return dtlist;
}
What basically I am doing is getting the datelist using the GetDates function and then depending on the isIncludeBaseDate bool value(if true) skipping the last date and adding the Base Date
It is working fine but can this program can be improve?
I am using C#3.0 and Framework 3.5
Thanks
You're doing too many temporary list-conversions; you can keep all the work as a query until the very end, that way it'll only be evaluated once.
public static List<DateTime> GetOnlyFridays(DateTime endDate, int weeks, bool isIncludeBaseDate)
{
var fridays = GetDates(endDate, weeks)
.Where(d => d.DayOfWeek == DayOfWeek.Friday);
if (isIncludeBaseDate)
{
fridays = fridays.Skip(1)
.Concat(new []{endDate});
}
return fridays.ToList();
}
You don't need to convert to a list immediately. For example, the following should work just as well, but without the need to convert the result to a list (it allows you to loop over them in a foreach loop, for example, without ever having to instantiate an entire list. If you pass in a large number for weeks that could be a big saving in terms of memory usage):
public static IEnumerable<DateTime> GetOnlyFridays(DateTime endDate, int weeks, bool isIncludeBaseDate)
{
var fridays = from dtFridays in GetDates(endDate, weeks)
where dtFridays.DayOfWeek == DayOfWeek.Friday
select dtFridays;
if (isIncludeBaseDate)
{
return fridays.Skip(1);
}
return fridays;
}
I would also try finding the closest friday at or before 'endDate', then for as many weeks we have, do a DateTime.AddDays(7); and of course take into consideration isIncludeBaseDate.