Cleaner way of dealing with dates in java / Quartz - date

In order to programmatically schedule a job one day ahead (using quartz) I had to come up with this mess of code:
Date.from(LocalDateTime.from(Instant.now()).plusDays(1).toInstant(ZoneOffset.ofHours(-3)))
Isn't there a way of making this monstruous piece of code more clean, readable?
My goal is to simple pick this moment and add one day to it, no concerns about timezones or little differences in the duration of some given days.
EDIT
To be more specific, I need a java.util.Date that represents one day more than when it is created.

The title you picked asks for dates in Java in a general sense, but your question and your tags show that you might be interested in some Quartz-specific solutions, like these (assuming you're using TriggerBuilder):
TriggerBuilder tb = ...; // initialize your tb
// Option 1
Trigger trigger = tb
.withSchedule(/* pick your flavor */)
.startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.DAY))
.build();
// Option 2
LocalDateTime now = LocalDateTime.now();
Trigger trigger2 = tb
.withSchedule(/* pick your flavor */)
.startAt(DateBuilder.tomorrowAt(now.getHour(), now.getMinute(), now.getSecond()))
.build();
For more info check the DateBuilder API.

There are two forms with no preference I know of for one or the other. Either this one:
Date sameTimeTomorrow = Date.from(Instant.now().plus(Duration.ofDays(1)));
Or this:
Date sameTimeTomorrow = Date.from(Instant.now().plus(1, ChronoUnit.DAYS));
Beware, however, that this adds 24 hours without any consideration of summer time or other anomalies. For example: In my time zone summer time ends in the night between October 27 and 28. So if I run the above on October 27 at 12 noon I will hit October 28 at 13 in my time zone because the time has changed. If I need to hit 12 noon again, I need:
Date sameTimeTomorrow = Date.from(
ZonedDateTime.now(ZoneId.of("America/Sao_Paulo")).plusDays(1).toInstant());
Please substitute your correct time zone.

Related

Hi, I need to display data from a table (vw_tracking_resource_events), but only 14 days of data for a certain time (18:00 to 19:00)

I use PostgreSQL
I can run a single query per day, but it will take a long time to go through every day.
The "zone" and "reader" also changes, so to run single queries every time will keep me up until late.
If at best I can only change the "reader" and "zone" every time it would help. The main "PAIN" I have, is to change the dates every time. It will be from 2022 11 18 18:00 to 2022 12 01 19:00.
P.S - I'm new to SQL, please be gentle :)
My current query:
select * from vw_tracking_resource_events
where "when_enter_dt_timezone" between '2022 11 18 18:00:00' and '2022 11 18 19:00:00'
and "zone" = '085 Level'
and "site" = 'MK'
and "reader" = 'RV Shaft'
and "group" = 'Lamp'
If you cast your field to separate and compare the date part and the time part to desired ranges, it becomes super easy:
WHERE when_enter_dt_timezone BETWEEN '2022-11-18' AND '2022-12-01T23:59:59.999'
AND when_enter_dt_timezone::time BETWEEN '18:00' AND '19:00'
Edit:
#Stefanov.sm makes a very good point regarding the casting of the timestamp to type date (1st criterion above) if an index can be used to retrieve data.
I corrected the query to take his remark.
Disclaimer: With when_enter_dt_timezone::date BETWEEN ... AND 2022-12-01, you include e.g. 2021-12-01T18:30.
Without the cast, the upper bound 2022-12-01 is implicitly set to midnight (morning); you will either have to change the upper bound to 2022-12-02 (which #Stefanov.sm suggested and works very well since you have a condition on the time anyway) or set your upper bound to 2022-12-01T23:59:59.999 (which is what I did above, although only to draw your attention to this specific issue).
You can try something like this to get records for the last 14 days between 6:00 p.m. and 7:00 p.m.
select * from vw_tracking_resource_events
where when_enter_dt_timezone > current_date - interval '14' day and
when_enter_dt_timezone::time between time '18:00' AND time '19:00'
Demo in sqldaddy.io
Modified using #Atmo notes
and #a_horse_with_no_name

Why is Date.getMinutes() returning 2 for the time 4:00 PM?

I'm creating a customized function that does some calculations for a given time.
When a time is entered in a cell, for example 4:00 PM, this is automatically converted into a date, in this case 12/30/1899 16:00:00 and when the function getTheMinutes() is called, it returns 2 instead of 0.
function getTheMinutes(dateTime){
return dateTime.getMinutes();
}
The behavior of the function is different if it's used for a most recent date like 5/1/2019 16:00:00.
I want the user to be able to just write a time in a cell then use the customized function in another cell. Please let me know your thoughts.
Now that you have indicated the time zone for your spreadsheet I can confirm what #RobG deduced almost a day ago, which is that Guatemala adjusted its difference relative to UTC. Something you have confirmed is treated as by two minutes with effect from October 5, 1918.
More specifically, the adjustment was of 2 minutes and 4 seconds and effective from 03:00 that day:
(Source IANA Version 2019b file northamerica.)
There have been very many such minor adjustments around the world over the years (even between towns in the same country) and adjustments continue, though usually of a whole hour – between 'standard' and Summer time. Sheets has very properly recognised that "normal arithmetic" 'does not work' across such a transition and while noon yesterday to noon today for example is normally, for any one specific location, a difference of 24 hours it is often 23 hours or 25 hours on the day that clocks go forward/back.
And the moral of the story is to beware of obliging Sheets to assume, for want of a specific date, that is has the index number 0 - i.e. is December 30, 1899.
I made some testing, and I found out that the formula is giving a wrong result any minute before 10/5/1918 0:03:00, from that DateTime on, the formula is working as expected.
Here is my sheet https://docs.google.com/spreadsheets/d/1psm8_GJYRczO53TILJCOzo0p4GpnS-ooiGWqOJrC8ZU/edit?usp=sharing
I would need to do a date validation in my customized formula to make it useful. I don't know why google sheets is choosing that date as default when just a time is typed in a cell, I think it should be improved.

Difference between two ZonedDateTime in Period

Using LocalDate, I got the difference expressed in a Period instance. For example:
LocalDate born = LocalDate.of(1990, Month.SEPTEMBER, 30);
Period myAge = Period.between(born, LocalDate.now());
System.out.println("My age is: "+myAge.getYears()+" years "+myAge.getMonths()+" months "+myAge.getDays()+" days.");
Output:
My age is: 26 years 6 months 23 days
So, I was using period to get the age in years, months and days.
I would like to do the same with ZoneDateTime using two time zones (US/Pacific and Australia/Melbourne). For example:
ZonedDateTime now = ZonedDateTime.now(); // US/Pacific
LocalDate date = LocalDate.of(1990, Month.SEPTEMBER, 30);
LocalTime time = LocalTime.of(23, 55);
ZoneId zone = ZoneId.of("Australia/Melbourne");
ZonedDateTime born = ZonedDateTime.of(date, time, zone);
I would like to get the same output as I got with LocalDate. What should I do? Does it make sense?
Expected output:
My age is: 26 years 6 months 24 days
The first line of Period documentation state that it is a date based amount of time in ISO-8601 format. It is not meant to be used with XXXTime.
However, ZonedDateTime offer you an until method which will return the number of a given ChronoUnit until another Temporal (now in your case).
For example :
born.until(now, ChronoUnit.YEARS);
would return 26.
One trick is to add the difference retrieved to the starting date and then process the next ChronoUnit
For example :
long years = born.until(now, ChronoUnit.YEARS);
born = born.plusYears(years);
long months = born.until(now, ChronoUnit.MONTHS);
born = born.plusMonths(months);
long days = born.until(now, ChronoUnit.DAYS);
And then you can print your variables.
Rather than using a ZonedDateTime for a birth date, I'd recommend storing a LocalDate and a ZoneId (ie. in separate fields/columns).
The simple answer to getting the Period from two LocalDate instances is to call toLocalDate() on both. As you'll realise, there is the problem that those ZonedDateTime instances might be in different time-zones, which might require work to normalize. But again, I'd stress that the better storage for this data is two fields - LocalDate and a ZoneId.
Period p = Period.between(born.toLocalDate(), now.toLocalDate());
// warning! the above ignores time-zones, assuming both are the same
If you need the difference between the two in Period plus Duration (for the remaining seconds), you can use this:
Period p = Period.between(born.toLocalDate(), now.toLocalDate());
Duration d = Duration.between(born.with(now.toLocalDate()), now);
The final option is to use ThreeTen-Extra. The soon to be released v1.1 will contain a class PeriodDuration that combines a Period and a Duration and allows the amount of time between two LocalDateTime instances to be stored.
The primary reason you should use LocalDate to represent birthday is because everyone observes their birthday the same way, or put another way, everyone observes their birthday using the clock according to where they are currently at. If you were born in France, and right now are living in the US which has a different timezone offset, you wouldn't celebrate your birthday by observing France's current date, you would instead check the date where you are currently which is local to you. Temporal classes with timezone support should be used for events that span regions, for example, flight arrivals and departures tracking software. So using ZonedDateTime to describe birthday is not wrong, it is semantically incorrect.
Also, Period implements TemporalAmount which obviously represents a span of time. So using it to represent birthday is (again) not wrong, but it makes your intention less clear. Birthday is an exact moment on the timeline, not a duration, so all in all, LocalDate is the best choice

Swift: Next instance of certain time on soonest date

I'm working with Swift 2.1 to build an app that sets repeated reminders. This consists mainly of two parts:
The user can select a time at which reminders must begin (e.g. 09:00)
The user can choose to have it repeat every X hours (e.g. if it's six hours, then the reminders would be set at 09:00, 15:00, 21:00, 03:00)
I'm using CVCalendarKit to manipulate certain date units, so part 2 (adding X hours every time) isn't the trouble I'm having.
What I'm trying to figure out is if there's an easy way to create an instance of NSDate with the soonest instance of a certain time.
So, assuming today is 13th of February 2016,
If it's 8:59, the NSDate created should be 2016-02-13 09:00:00
If it's 9:01, the NSDate created should be 2016-02-14 09:00:00
Many thanks in advance.
You can use NSCalendar.nextDateAfterDate()
let calendar = NSCalendar.currentCalendar()
let now = NSDate()
let nextTime = calendar.nextDateAfterDate(now,
matchingHour: 9,
minute: 0,
second: 0,
options: NSCalendarOptions.MatchNextTime)
If you aren't using the open source Swift Foundation libraries, this only works on iOS 8+ or OS X 10.9+
Watch out for changes in daylight savings time.
Quite soon there will a day where one hour is missing. In that case you (or your user) must make two decisions: 1. What happens if the date you are interested in doesn't exist? (For example, there will be one day in the year in the UK where "2:30 am on the next day" doesn't exist). 2. What do you mean by "every six hours"? On one day of the year, "6 hours after 21:00" is "04:00" on the next day.

Difference between dates from Database in another location and client's local time

I have a requirement to disregard records from the DB that are more than 10 minutes old. However, the DB server is present in a different time zone than the app server. I tried to leverage the time zone details from the timestamp column value but it seems that they do not store the time zone details in that column value (bad design?). However, i have found a way to get this information for the DB instance using a query:
select dbtimezone from dual.
However, most of the implementations in java support time zones via names and not offset information. I need to be able to translate this offset exactly to a timezone (EST etc) so that i may not miss any DST related time in my calculations. like so:
TimeZone dbZone = TimeZone.getTimeZone(10000); // offset is +10000
Calendar cal = Calendar.getInstance(dbZone);
cal.setTime(new Date());
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
df.setTimeZone(dbZone);
Date parsedDate = df.parse(df.format(cal.getTime()));
The plan is to convert the present client/app time to the DB specific timezone time and perform the difference between the two.
This cannot be done in a query due to some restraints. Please do not ask me to write a query to get latest records etc. Must be done in Java.
Any tips?
I am guessing it might get you in the right direction. You can try the following so you know the offset from EST and can do the calculation accordingly:
SELECT TZ_OFFSET('US/Eastern') FROM DUAL;
So a return of -3:00 would mean it is PST time. Maybe you've already tried this?