Creating specific time stamps for objects? - java

I'm not trying to use the current time at all. Im aware of the calendar and date java utils but I'm not sure how to create my OWN timestamps not dependent on the current time. For instance each object would have an "arrival time" variable in hh:mm:ss format. But I have no clue how to do this. Do I have to create my own class?

It’s not perfectly clear, but I would think you’re after something like this:
public class MyObject {
private static final DateTimeFormatter ARRIVAL_TIME_FORMATTER
= DateTimeFormatter.ofPattern("HH:mm:ss");
// Some instance variables
private LocalTime arrivalTime;
public MyObject(LocalTime arrivalTime) {
this.arrivalTime = arrivalTime;
}
public String getFormattedArrivalTime() {
return arrivalTime.format(ARRIVAL_TIME_FORMATTER);
}
}
As has been said in the comments, use a LocalTime for the time of day. Don’t worry about format when storing the arrival time in your object. Only format it when you need to display it. LocalTime.of creates a LocalTime not related to the current time. There are overloaded versions that also take seconds.
So no, don’t create your own timestamp class. Use LocalTime (or depending on requirements some other class) from java.time, the modern Java date and time API.
Let’s see a brief example of using the above MyObject class:
MyObject obj = new MyObject(LocalTime.of(23, 45));
System.out.println("Object arrived at " + obj.getFormattedArrivalTime());
Output:
Object arrived at 23:45:00
In the output (and there only) the time has been formatted to hh:mm:ss as you requested.
Edit: LocalTime has a precision of nanoseconds. Basil Bourque is correct in his comment that if you know that you don’t want to store any finer precision than whole seconds, it’s easy to truncate the incoming value:
public MyObject(LocalTime arrivalTime) {
this.arrivalTime = arrivalTime.truncatedTo(ChronoUnit.SECONDS);
}
On one hand I’d hesitate to throw information away like this, and time stamps tend to benefit from precision. On the other hand it may also be confusing if your object stores a fraction of second that no one ever sees. You will have to decide yourself.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Documentation of LocalTime

Related

Convert Long to LocalDateTime [duplicate]

This question already has answers here:
Jackson deserialize elasticsearch long as LocalDateTime with Java 8
(2 answers)
Closed 1 year ago.
I receive this error when trying to get response from Api Call:
I receive this field like this from the object:
"createdAt":1620133356550
My Dto has this field, so i can get the value with object mapper:
#JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime createdAt;
And i receive this error:
com.fasterxml.jackson.databind.exc.MismatchedInputException: raw timestamp (1620133356550) not allowed for `java.time.LocalDateTime`: need additional information such as an offset or time-zone (see class Javadocs)
Possible setter of the object:
public void setCreatedAt(long createdAt) {
Instant instant = Instant.ofEpochMilli(createdAt);
LocalDateTime localMark =
instant.atZone(ZoneId.of("Europe/Amsterdam"))
.toLocalDateTime();
this.createdAt = localMark;
}
That's because you're asking jackson to silently convert an apple into a pear and it won't do that. There is no way to do this without additional information.
This: 1620133356550 looks like a milliseconds-since-epoch value.
This represents an instant in time. Instants in time and LocalDateTime are a real guns and grandmas situation: They are almost entirely unrelated, and one cannot be transformed into the other; at least, not without parameters that are simply not present here.
First you need to 'localize' the timestamp: That's milliseconds since some instant in time. Which instant in time? A common format is 'milliseconds since midnight, new years, 1970, in the UTC timezone'. If that's indeed what it is, all you need to do is to say Instant.ofEpochMilli(1620133356550L), and you now have that properly represented (namely, as an Instant).
This still isn't a LocalDateTime though. The problem is: Local to whom?
UTC isn't actually used by anybody except space flight, aviation in general, and computers talking to each other. Unless you're writing software specifically intended to run on the Dragon space capsule and nowhere else, by definition then this isn't yet ready to be put in terms of local date and time.
First you need to transform your instant to a locale. THEN you can have a LocalDateTime.
For example, if you want to know: Okay, so if I walk around Amsterdam at the exact instant as represented by this java.time.Instant I made, and I ask somebody the date and time, what would they say? Then you do:
Instant instant = Instant.ofEpochMilli(1620133356550L);
LocalDateTime localMark =
instant.atZone(ZoneId.of("Europe/Amsterdam"))
.toLocalDateTime();
In case this is some bizarro format where a LocalDateTime is serialized by way of: Take the local date time, turn that into an instant by assuming you're asking the current date and time at that exact instant by asking someone zipping about the international space station, and then turn that into epochmillis and put that on the wire, okay, then, write that. Use ZoneOffset.UTC instead of ZoneId.of("Europe/Amsterdam") in the above code.

Difference between 2 Dates not calculating time difference

I request a Date in a Controller with
#GetMapping(path = "/{terminal}/{date}",consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ServiceResponse appointmentsListDate(#PathVariable Long terminal, #PathVariable #DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date date) {
Then I need to compare that Date with a stored date in database (type = timestamp without time zone).
I´m using the methods before() and after() but it fails when comparing the time part (the date comparison is good, but it doesn´t compare the time).
public Collection<EntrySlot> getAppointment( Date date) {
Collection<EntrySlot> entrySlotList=new ArrayList<>();
for(int i=0; i<appointmentList.size();i++){
Appointment appointment = ((List<Appointment>)appointmentList).get(i);
EntrySlot entrySlot = appointment.getIdEntrySlot();
if (date.before(entrySlot.getStartDate())){
entrySlotList.add(entrySlot);
}
return entrySlotList
}
At example of the entrySlot.getStartDate stored in db is 2021-05-01 16:00:00. My date is 2021-05-01 17:00:00 and when using the date.before(entrySlot.getStartDate) the result is true.
I don´t know if the problem is related to the date formatting.
Thanks in advance!
PD: I have solved the problem. The hour stored in the database has GMT+2 hours. I had to substract those hour and now I can calculate the difference even using the deprecated date.util.
java.util.Date is a lie; it does not represent dates. It presents moments in time.
'timestamp without timezone' is something completely different. You're asking the system: Hey, I have this apple. Is it better than this pear?
It'd have been better all around if the code had failed to compile but for complicated reasons, it does compile. Nevertheless, it is gobbledygook.
First, compare all the times you have into the data type that properly represents the concept of 'timestamp without timezone', which is java.time.LocalDateTime.
Most DB engines can give you this directly; at the JDBC level, call .getObject(idxOrColName, LocalDateTime.class). A few rusty old JDBC drivers can't do this, in which case you're forced to call e.g. .getTimestamp, which will convert a timestamp-without-timezone in-flight to a moment-in-time-devoid-of-context, and you then have to unconvert this messed up conversion, preferably ASAP.
Once you have that, put your target in terms of LocalDateTime as well, and now compare the two. If it fails now, you can just debug each process individually, because then one of the two processes that end in you having an instance of LDT, is broken and it is instantly obvious which one: It's the one where printing that LDT does not show what you expected.
NB: All date/time related classes in java.util, java.sql, and the (Gregorian)Calendar class are obsolete and bad API which lead to exactly the problems you have now. Don't use those, or if you're forced into it, convert them to a java.time type immediately and debug this conversion on its own before continuing with the program.

How can we decide whether to use ZonedDateTime or LocalDateTime?

Sometimes, we find it is difficult to make judgement, whether to use ZonedDateTime or LocalDateTime, when we want to solve certain date/ time problem.
For instance, given an epoch, we would like to know the day of the week.
We find we can accomplish this task, with either ZonedDateTime or LocalDateTime. Here's the code example
import java.time.*;
public class Main {
public static void main(String[] args) {
long currentTimeMillis = System.currentTimeMillis();
// Yield correct result.
System.out.println("useLocalDateTime -> " + useLocalDateTime(currentTimeMillis));
// Also yield correct result.
System.out.println("useZonedDateTime -> " + useZonedDateTime(currentTimeMillis));
}
public static DayOfWeek useLocalDateTime(long currentTimeMillis) {
LocalDateTime localDateTime = LocalDateTime.ofInstant(
Instant.ofEpochMilli(currentTimeMillis),
ZoneId.systemDefault()
);
DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();
return dayOfWeek;
}
public static DayOfWeek useZonedDateTime(long currentTimeMillis) {
ZonedDateTime zonedDateTime = Instant.ofEpochMilli(currentTimeMillis).atZone(ZoneId.systemDefault());
DayOfWeek dayOfWeek = zonedDateTime.getDayOfWeek();
return dayOfWeek;
}
}
In the above case, is it better to use ZonedDateTime or LocalDateTime? Is there any guideline, so that we can pick up the correct class as tool?
I always have the impression that ZonedDateTime is more "feature rich" than LocalDateTime. Whatever can be accomplished by LocalDateTime, it can be accomplished by ZonedDateTime too, but not vice-versa. Hence, if I get stuck on which to choose, I will go to ZonedDateTime as default. Is that a correct concept?
Do you need to store time data that is attached to a specific time zone, or do you need to process time data that has an associated offset?
If you do, use ZonedDateTime.
If you don't, use LocalDateTime.
Some examples of when I would want to use ZonedDateTime:
I'm parsing an ISO 8601 timestamp with zone information.
I'm looking at data from two different sources located in two physically different locations.
I'm trying to calculate what the day of the week is given a timestamp.
Some examples of when I would want to use LocalDateTime:
I'm assured that my system only needs to care about one time zone - mine.
The data that I'm parsing does not have time stamp information.
I want to know how many seconds have passed between two time stamps. This may get converted to a ZonedDateTime first before it eventualy decants into a Duration if the time stamps are in ISO 8601 format.
Definitely be careful about days of the week across time zones, since the International Date Line can offset the day of the week depending on where you are physically located.
Instead of using System.currentTimeMillis() use ZonedDateTime.now(ZoneId) or Instant.now(). You should almost never need currentTimeMillis() in modern Java. Use the dedicated java.time APIs throughout your application, so that you're working with well-typed data structures instead of primitives like long currentTimeMillis.
given an epoch, we would like to know the day of the week
It's worth recognizing that this isn't a meaningful question without a time zone; at any moment in time there are two (or more?) days of the week in different places on earth. So before we go further we need to ask which time zone(s) do you care about?
Generally speaking, the systemDefault() time zone is not what you want. Instead the caller should provide the time zone they expect. If your program is running locally and only ever needs your machine's clock it may be fine, but the very reason for the split between LocalDateTime and ZonedDateTime is because the system is very often not the correct time zone to be using.
For trivial cases, e.g. a Java process running on your local machine that doesn't care about time zone changes over time, you might correctly use the system time zone. But in such cases it's a good idea to query the system near your main() method and then pass that zone through your application. This makes the application more scalable and testable, if the system zone stops being the right approach down the road.

More precision in comparing two dates, that are two hours appart

Can this be tested with more precision? This is a simple function that calculates executionStartTime as two hours behind currentTime.
Function below works, but I would like a function that is more precise.
#Test
public void testCalculateExecutionStartTime() {
Date currentTime = new Date(ZonedDateTime.now(ZoneOffset.UTC).toEpochSecond() * 1000);
Date executionStartTime = proxy.calculateExecutionStartTime(properties.getMessageConfiguration().getExecutionStartTime());
Assert.assertTrue(currentTime.after(executionStartTime));
}
I am assuming that calculateExecutionStartTime is returning a time that is two hours ago compared to the time you call the method, and this is what you want to test. In my first suggestion I am further assuming that you can change the method to return a modern Instant instead of an outdated Date. Since you can use java.time, the modern Java date and time API, this would immediately look like an easy improvement.
The challenge is that the call may take some milliseconds, even some seconds, and we don’t know at what point in time during the call it is reading the clock. So there is no testing using assertEquals with the time that we expect. Instead we read the clock before and after the call. Then our test can rely on the method reading the clock at some point between our two calls. In most cases this will allow us to test the returned time with just a small margin. The idea was already presented by Dawood ibn Kareem in a comment.
#Test
public void testCalculateExecutionStartTime() {
Instant timeBefore = Instant.now();
Instant executionStartTime = proxy.calculateExecutionStartTime(
properties.getMessageConfiguration().getExecutionStartTime());
Instant timeAfter = Instant.now();
Duration expectedTimeAgo = Duration.ofHours(2);
Assert.assertFalse(executionStartTime.isBefore(timeBefore.minus(expectedTimeAgo)));
Assert.assertFalse(executionStartTime.isAfter(timeAfter.minus(expectedTimeAgo)));
}
Note the use of Instant.now() for reading the clock. You don’t need ZonedDateTime nor ZoneOffset.
If you cannot change the return type of calculateExecutionStartTime, just convert the Date you get from it:
Instant executionStartTime = proxy.calculateExecutionStartTime(
properties.getMessageConfiguration().getExecutionStartTime())
.toInstant();
The rest is exactly as before.

How to use java.util.Calendar in GWT

I have to use java.util.Calendar in GWT entry point, but I got error while running the application, that is because GWT is not able to find source code, is there anyway I could fix this issue.
Thanks in advance!!!
java.util.Calendar is not an emulated class. You can find a list of emulated classes here:
http://code.google.com/webtoolkit/doc/latest/RefJreEmulation.html
I would strongly advise not to use any date/calendar library on the client side. You will probably only get yourself into trouble. In fact, even though java.sql.Date and java.util.Date are emulated in GWT, I would not use these either. If you're looking to use Calendar, then chances are you want to support timezones on the client. Using the emulated Date classes, you will somehow have to convert the client's Date from the browser's timezone to some target timezone (GMT or whatever the user defined in user preferences?). This will most definitely be error prone. Using GWT's TimeZone adds other issues. For instance, how do you map between java TimeZones and GWT TimeZones?
I recommend doing all date manipulation AND formatting on the server. On the client, you can simply use a date/month/year triplet. The server can have an association between user (or organization) and java.util.TimeZone (or joda timezone). Using the triplet and timezone you can easily create the specific instance in time.
You may be able to use com.google.gwt.user.datepicker.client.CalendarUtil.
No there is no way to use the java.util.Calendar in GWT because there is no equivalent in JavaScript. But there is an accepted feature request for it. Maybe you will find some hints in the comments of the request.
The following shows how to use Joda Time to extract any date information from a Java Date type with Joda Times format() function and use it to build a new Date() using Joda Time's parse() function.
static DateTimeFormat dtf = DateTimeFormat.getFormat("yyyy-MM-dd HH:mm:ss.SSS");
static DateTimeFormat datefmt = DateTimeFormat.getFormat("yyyy-MM-dd ");
static DateTimeFormat timefmt = DateTimeFormat.getFormat("HH:mm:ss.SSS");
public Date getDateTime(Date date, Date time) {
String datetime = datefmt.format(date) + timefmt.format(time);
return dtf.parse(datetime);
}
Have you tried adding actual code of the class to your project? Some Java SDK classes compile well even though they are not in JRE white list.
For those who prefer implementing the math directly, here is a solution for how to add days to an existing date object without using Calendar or any deprecated functions:
private Date addDays(Date dateIn, int numDays)
{
long milisPerDay = 86400000;
// convert the dateIn to milliseconds
long dateInMilis = dateIn.getTime();
// add numDays to the date
dateInMilis = dateInMilis + (numDays * milisPerDay);
return new Date(dateInMilis);
}
Here's how to get the current year as a String (very useful for Copyright notices)
long time = System.currentTimeMillis();
long milisPerYear = new BigInteger("31536000000").longValue();
String currentYear = String.valueOf((int) Math.floor(time / milisPerYear) + 1970);
Finding the constants such as number of miliseconds in a day, year, etc. is easy with Google. The tricky part is adding months, since the number of milliseconds in a month is going to depend on the month. If there's any demand for it, I'd be happy to write a function and post it here in order to add and subtract months.

Categories

Resources