How can I tell if DateTime.Now() is on a day AFTER a different DateTime - date

I'm running this on flutter, but I guess this could be a more general issue.
I am saving a DateTime in the preferences. I want to be able to then tell if DateTime.now() is on at least a day after the last saved DateTime, i.e.
(pseudocode)
lastDailyCheck = 2020.04.10
now = 2020.04.11
=> now is a day after the lastDailyCheck.
This should already work if it is 00:01 on the new day, even if the lastDailyCheck was on 23:58 the day before, meaning the difference can be as low as minutes between the 2 DateTimes.
Turns out this is really complicated!
Here's what doesn't work:
DateTime.Now().isAfter(lastDailyCheck)
This only checks if now is after the last one, it also return true after a second, and on the same day.
DateTime.Now().isAfter(lastDailyCheck) && lastDailyCheck.day != DateTime.Now().day
I thought this was clever. If the day is different and it is after the last then it does work in recognizing it is a day later - but then I realized it would bug out when both days are say on the 15th of the month - then lastDailyCheck.day would equal DateTime.Now().day.
What do you think would be possible here?

I don't know flutter, but my approach would be to not store the last check, but store the date at which the next check should occur. So when you perform a check you calculate the next midnight and store that. Now you can use isAfter.
In javascript this would look something like this:
const now = new Date();
//this also handles overflow into the next month
const nextCheck = new Date(now.getYear(), now.getMonth(), now.getDate() + 1)
//store nextCheck somewhere
//in js there is no isAfter, you just use >
if(new Date() > nextCheck) {
//do the thing
}
of course you could also calculate nextCheck every time you want to compare it, but I dislike performing the same calculation over and over if I can avoid it.
A thing to mention here is timezones, depending on your date library and if your system and user timezones align, you may need to shift the date.

I cannot write a complete code for now but this is what it would look like:
(pseudocode)
expirationDay = lastDailyCheck.add(oneDayDuration);
isOneDayAfter = DateTime.now().isAfter(expirationDay);
You give an expiration date and compare the DateTime to that. You have to use isAfter for reliability, instead of .day check.

I would compute the difference between midnight of the day of the last timestamp and midnight of the current timestamp. That is, consider only the date portion of a DateTime and ignore the time.
DateTime date(DateTime dateTime) =>
DateTime(dateTime.year, dateTime.month, dateTime.day);
// Intentionally check for a positive difference in hours instead of days
// so we don't need to worry about 23-hour days from DST. Any non-zero
// number of hours here means a difference of at least a "day".
if (date(DateTime.now()).difference(date(lastDailyCheck)).inHours > 0) {
// "One day" after.
}
If you're using UTC timestamps and don't care about when midnight is in whatever the local time is, the comparison could more intuitively use .inDays >= 1.

Figured out another potential solution!
In addition to checking if the day is different (which by itself won't work) you can also check the month and year. Only 1 of those needs to differ for it be true :)
if (now.isAfter(lastDailyCheck)) {
if (now.day != lastDailyCheck.day ||
now.month != lastDailyCheck.month ||
now.year != lastDailyCheck.year) {
return true;
}
}

this is the way I prefer to do some logics based on the comparison between two different times:
var now = DateTime.now();
var myDate = new DateTime.utc(2022, 1, 1);
if(myDate.compareTo(now)>0) //positive value means myDate is greater than DateTime.now()
{
// here is your logic based on the comparison between two times
} else {
//your logic if DateTime.now() pass myDate
}

You can use the difference method to get the difference between 2 dates and check whether those differs in hours with at-least 24 hours. So your if condition becomes:
if (now.isAfter(lastDailyCheck) &&
(lastDailyCheck.day != now.day ||
now.difference(lastDailyCheck).inHours > 24)) {
print('After');
}

Here's an attempt to a succint answer. Simply export this extension and use it. With it you can say if a date is at least one day after the current day.
extension DateExt on DateTime {
bool isAtLeastOneDayAfterToday() {
final now = DateTime.now();
return (isAfter(now) &&
(day != now.day || month != now.month || year != now.year));
}
}
Use it like so:
final isAfter = myDay.isAtLeastOneDayAfterToday(); //will be true or false

Related

Codename One days left in current week or month

I am building a calendar application that needs to calculate the remaining days of (1) the current week and (2) the current month.
What I have tried was using the java.util.Calendar API, but it seems not to be fully supported.
int days = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
How would I do this in CN1?
Many thanks in advance.
We would love to add support for JSR310 in the future which would probably solve this in a more elegant way. This is something that can be done as a cn1lib without modifying Codename One but would require some work...
A bit of a hack to do this is:
int month = cal.get(Calendar.MONTH);
cal.set(Calendar.DAY_OF_MONTH, 1);
if(month == cal.DECEMBER) {
cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + 1);
cal.set(Calendar.MONTH, Calendar.JANUARY);
} else {
cal.set(Calendar.MONTH, month + 1);
}
int day = 24 * 60 * 60000;
cal.setTime(new Date(cal.getTime().getTime() - day));
I don't know CN1, but you can calculate the values using a subtraction between the max and the current value:
(1) cal.getActualMaximum(Calendar.DAY_OF_WEEK) - cal.get(Calendar.DAY_OF_WEEK)
(2) cal.getActualMaximum(Calendar.DAY_OF_MONTH) - cal.get(Calendar.DAY_OF_MONTH)
For your notification: The first day of the week is sunday in the api of calendar. When your week should start with monday you have to reduce the offset by 1.

Setting up a two week timetable in Swift

NOTE: I am a new Swift programmer, a NOOB if you will.
I am creating a school timetable app just for personal use to practise my coding. However, our school operates on a two week time table system, with 10 days, labeled 1 through to ten. I am wondering if anyone had some ideas as to how I could work out whether the current date is day one or day nine or day 4. I know I could use if statements for the dates, but the would take a long time, and require manual input of the dates. How could I have the app keep count of what day it is, skipping weekends?
EDIT - I could maybe have 14 days, with days 6,7,13 and 14 empty.
FOR EXAMPLE:
The current date is OCT 4, this is day one. I would like the app to be able to work out what day of the timetable the current date is. This would then load the appropriate day (e.g. Subject, Teacher, Classroom). Day One is Monday, Two is Tuesday, Five is Friday, Six is Monday, 10 is Friday. Could I have some sort of rostering system?
I am sorry if the question is vague, please tell me if I need to clarify.
I have been working on a fix for weeks now, so I have decided to turn to help. Any guidance whatsoever would be much appreciated, as I am at a dead end!
Many thanks
The numbers that I'm plugging into this example probably don't match your requirements but consider this as a strategy. (In this case, using a 1-to-14 cycle. If you'd rather get 1-to-10 you can put in a subtraction and a different error to throw on the "bad" days.)
class CyclicDay {
enum CyclicDayError: ErrorType {
case InvalidStartDate
}
lazy var baseline: NSDate? = {
// Set up some start date that matches day 1
var components = NSDateComponents()
components.day = 6
components.month = 9
components.year = 2015
return NSCalendar.currentCalendar().dateFromComponents(components)
}()
func dayOfCycle(testDate: NSDate) throws -> Int {
if let start = baseline {
// Convert difference to days
let interval = testDate.timeIntervalSinceDate(start)
let days = interval / (60 * 60 * 24)
// Convert to value 1..14 to position in a 2-week cycle
return Int(days % 14) + 1
}
throw CyclicDayError.InvalidStartDate
}
}
// Test today
let cd = CyclicDay()
let day = try cd.dayOfCycle(NSDate())

What is the most efficient way to convert an eight digit number to a date?

I am using ColdFusion 9.0.1 and some database that I cannot change.
I am accessing a database that stores a date as an eight digit numeric with zero decimal places like this:
YYYYMMDD
I need to be able to read the date, add and subtract days from a date, and create new dates. I am looking for a ColdFusion solution to efficiently (not much code) to convert the date to our standard format, which is
MM/DD/YYYY
And then convert it back into the database's format for saving.
I need to code this in such a way that non-ColdFusion programmers can easily read this and use it, copy and modify it for other functions (such as adding a day to a date). So, I am not looking for the most least amount of code, but efficient and readable code.
Can you suggest anything that would make this code block more flexible, readable, or more efficient (less code)?
<cfscript>
// FORMAT DB DATE FOR BROWSER
DateFromDB = "20111116";
DatedToBrowser = createBrowserDate(DateFromDB);
writeOutput(DatedToBrowser);
function createBrowserDate(ThisDate) {
ThisYear = left(ThisDate, 4);
ThisMonth = mid(ThisDate, 4, 2);
ThisDay = right(ThisDate, 2);
NewDate = createDate(ThisYear, ThisMonth, ThisDay);
NewDate = dateFormat(NewDate, "MM/DD/YYYY");
return NewDate;
}
// FORMAT BROWSER DATE FOR DB
DateFromBrowser = "11/16/2011";
DateToDB = createDBDate(DateFromBrowser);
writeDump(DateToDB);
function createDBDate(ThisDate) {
ThisYear = year(ThisDate);
ThisMonth = month(ThisDate);
ThisDay = day(ThisDate);
NewDate = "#ThisYear##ThisMonth##ThisDay#";
return NewDate;
}
</cfscript>
First find who ever did the database and kick them in the nads...
Personally I'd Convert with sql so my code only dealt with date objects.
Select Convert(DateTime, Convert(VarChar(8),DateTimeInventedByIdjitColumn))
From SomeTable
As stated by our peers, store dates as dates.
'08/06/2011' could be 8th of june of the 6th of August depending on locale.
20111643 is a valid integer..
Not using a proper date type is just a massive collection of features and bugs that at best are waiting to happen.
You can actually rewrite each function into 1 line of code.
function createBrowserDate(ThisDate) {
return mid(ThisDate,4,2) & "/" & right(ThisDate,2) & "/" & left(ThisDate,4);
}
and
function createDBDate(ThisDate) {
return dateFormat( ThisDate, "YYYYMMDD" );
}
Don't keep dates as strings - keep dates as dates and format them when you need to.
If you can't correct the database to use actual date columns (which you should if you can), then you can use these two functions to convert to/from YYYYMMDD and a date object:
function parseYMD( YYYYMMDD )
{
if ( ! refind('^\d{8}$' , Arguments.YYYYMMDD ) )
throw "Invalid Format. Expected YYYYMMDD";
return parseDateTime
( Arguments.YYYYMMDD.replaceAll('(?<=^\d{4})|(?=\d{2}$)','-') );
}
function formatYMD( DateObj )
{
return DateFormat( DateObj , 'yyyymmdd' );
}
By using date objects it means that any level of developer can work with them, without needing to care about formatting, via built-in functions like DateAdd, DateCompare, and so on.
I'm not a regular expression fan since it's not that readable to me.
Since you're using CF9, I'd typed the argument and specify the returntype of the functions to be even more readable for the next person picking up your code.
First, right after I read the date from DB, I'd parse it to a Date object using parseDBDate()
Date function parseDBDate(required String dbDate)
{
var yyyy = left(dbDate, 4);
var mm = mid(dbDate, 4, 2);
var dd = right(dbDate, 2);
return createDate(yyyy , mm, dd);
}
Once you have the date object, you can use all those built-in Date functoin like DateAdd() or DateDiff().
Call browserDateFormat() right before you need to display it.
String function browserDateFormat(required Date date)
{
return dateFormat(date, "MM/DD/YYYY");
}
Call dBDateFormat() inside <cfqueryparam value=""> when it's time to persist to DB
String function dBDateFormat(required Date date)
{
return dateFormat(date, "YYYYMMDD");
}
One liner :)
myDateString = "20110203";
myCfDate = createObject("java","java.text.SimpleDateFormat").init("yyyyMMdd").parse(myDateString,createObject("java","java.text.ParsePosition").init(0*0));
If you want to parse different patterns, change "yyyyMMdd" to any other supported pattern.
http://download.oracle.com/javase/1.5.0/docs/api/java/text/SimpleDateFormat.html
The ParsePosition is used to say where to start parsing the string.
0*0 is shorthand for JavaCast("int",0) - in the Adobe cf engine, 0 is a string, until you apply math to it, then it becomes a Double, which the ParsePosition constructor supports. Technically, it constructs with an int, but cf is smart enough to downgrade a Double to an int.
http://download.oracle.com/javase/1.5.0/docs/api/java/text/ParsePosition.html

Performance issue finding weekdays over a given period

I have some methods that return the number of weekdays between two given dates. Since calling these methods become very expensive to call when the two dates lie years apart, I'm wondering how these methods could be refactored in a more efficient way.
The returned result is correct but I feel that the iphone processor is struggling to keep up and consequently freezes up the application when I would call these methods over a period of say 10years.
Any suggestions ?
//daysList contains all weekdays that need to be found between the two dates
-(NSInteger) numberOfWeekdaysFromDaysList:(NSMutableArray*) daysList
startingFromDate:(NSDate*)startDate
toDate:(NSDate*)endDate
{
NSInteger retNumdays = 0;
for (Day *dayObject in [daysList objectEnumerator])
{
if ([dayObject isChecked])
{
retNumdays += [self numberOfWeekday:[dayObject weekdayNr] startingFromDate:startDate toDate:endDate];
}
}
return retNumdays;
}
-(NSInteger) numberOfWeekday:(NSInteger)day
startingFromDate:(NSDate*)startDate
toDate:(NSDate*)endDate
{
NSInteger numWeekdays = 0;
NSDate *nextDate = startDate;
NSComparisonResult result = [endDate compare:nextDate];
//Do while nextDate is in the past
while (result == NSOrderedDescending || result == NSOrderedSame)
{
if ([NSDate weekdayFromDate:nextDate] == day)
{
numWeekdays++;
}
nextDate = [nextDate dateByAddingDays:1];
result = [endDate compare:nextDate];
}
return numWeekdays;
}
You need to create an formula to calculate the number of weekdays rather than loop thru each day and count them.
Something like this (this is a rough approximation), where startJD and endJD are the Julian Dates:
nWeekdays = (endJD - startJD) * 5 / 7;
Of course that's close but not exact since it doesn't take into account what day of the week it starts and ends on. But that's the general idea, you need a formula, not a loop.
You can also find quite a bit on this topic by searching.
Why not look at the core foundation classes that handle dates?
CFAbsoluteTimeGetDayOfWeek
Returns an integer representing the day of the week indicated by the specified absolute time.
SInt32 CFAbsoluteTimeGetDayOfWeek (
CFAbsoluteTime at,
CFTimeZoneRef tz
);
Parameters
at : The absolute time to convert.
tz : The time zone to use for time correction. Pass NULL for GMT.
Return Value :
An integer (1-7) representing the day of the week specified by at. Per ISO-8601, Monday is represented by 1, Tuesday by 2, and so on.
Availability
Available in iOS 2.0 and later.
Declared In
CFDate.h
More can be found at: http://developer.apple.com/library/ios/#documentation/CoreFoundation/Conceptual/CFDatesAndTimes/

How to check/calculate the week-day count (using Date functions) using Javascript?

I would like to check if a given date is the first, second, third, fourth or last monday, tuesday, wednesday,..., sunday in the dates month.
The function should look like this:
if(checkdate(date, "second", "monday"))
{
alert("This is the second monday of the month");
}
else
{
alert("This is NOT the second monday of the month");
}
I would rather write a function that returns an object telling me the day and the week-number-in-month of the given date. Something like:
function infoDate(date) {
return {
day: date.getDay()+1,
week: (date.getDate()-1)%7+1
}
}
Then I can read the returned object and find out if it's the second monday or whatever:
var info = infoDate(date);
if(info.day==1 && info.week==2) {
// second monday
}
Of course, you can still write another localized function that does exactly what you ask for based on an array of numeral and day names.
use getDate() to get day of the month
then getDay() to get the day of the week
using these two you should be able to accomplish your task. Refer to this http://www.w3schools.com/jsref/jsref_obj_date.asp
It seems to me you only need to divide the date by 7 to know how many full weeks have passed, no matter what day it is. Subtracting one before dividing and adding it after sets the first week from 0 to one.
Date.prototype.weekofMonth= function(){
return Math.floor((this.getDate()-1)/7)+1;
}
alert(new Date().weekofMonth())