Ankit Srivastava
Ankit Srivastava

Reputation: 135

How to get Date from Timestamp object?

I am having date stored in this format in database 2019-07-03 12:14:11 so when I am getting it from database then it is coming with timestamp but I want only Date so that I can use it as a key of my TreeMap to order the TreeMap based on Date.

Eg.

Suppose I have data associated with these dates in database

2019-07-03 12:14:11 and
2019-07-03 12:14:27

Now both the dates are same but time is different so when I am storing in my TreeMap object

TreeMap<Date,List<Integer>> t=new TreeMap<>();

then inspite of date being same as time is different the TreeMap is storing the dates in different keys bubt I want as both the dates are same so data associated with both the dates should be stored in one key only.

If the data associated with first adte is 1 and second date is 2 the in TreeMap it should store under one key both 1 and 2 in List and if another data 3 is associated with 2019-07-01 12:12:12 then it should store in another key and keys should be sorted

I wrote this

if(map.containsKey(invoiceHeader.getInvoice_Date()))
            {

                List<Integer> invoicesList= map.get(invoiceHeader.getInvoice_Date());
                invoicesList.add(invoiceId);
                map.put(invoiceHeader.getInvoice_Date(),invoicesList);

            }
            else {

                List<Integer> invoicesList=new ArrayList<>();
                invoicesList.add(invoiceId);
                map.put(invoiceHeader.getInvoice_Date(),invoicesList);
            }

but here key is storing date and time both so even if

2019-07-03 12:14:11 and
2019-07-03 12:14:27

are same 2 keys are created and 1 is stored in one key and 2 in another key as getInvoice_Date() is fetching date and time as stored in database

How to achieve what I want?

Upvotes: 1

Views: 237

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 338256

Assuming you are storing the moment in your database in a column of a type akin to the standard-SQL TIMESTAMP WITH TIME STAMP, then retrieve the value from the database as a java.time.OffsetDateTime. The java.util.Date class is terribly flawed and was made legacy years ago with the adoption of JSR 310.

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

You say you care only about the date. But to get the date requires a time zone. The retrieved OffsetDateTime is likely in UTC, though that depends on your particular database system. The SQL standard does not specify much about date-time types. Most database I've encountered such as Postgres and H2 adjust any inputs into UTC in the process of saving to the database.

Remember that for any given moment, the date varies around the globe by time zone. It may be “tomorrow” in Tokyo Japan while still “yesterday” in Montréal Québec.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

Extract the date-only portion.

LocalDate ld = zdt.toLocalDate() ;

You would have already established your Map.

Map < LocalDate, List < Integer > > map = new TreeMap <> ( );

Let's hard-code an example of your Invoice identifier.

Integer id = 707;

You can shorten the code seen in Question by using putIfAbsent.

map.putIfAbsent ( ld , new ArrayList <> () );

Retrieve the List of Integer invoice id numbers.

List< Integer > list = map.get( ld ) ;

Add our invoice id.

list.add( id ) ;

We can combine those last two steps into one line.

map.get( ld ).add( id );

Upvotes: 1

Andreas
Andreas

Reputation: 159086

Don't use the ancient java.util.Date object. Use the new Java 8 Time API, i.e. parse the 2019-07-03 12:14:11 date string to a LocalDateTime object, then call toLocalDate() to get the date-only LocalDate value, which would then be the key in your map (Map<LocalDate, List<Integer>>).

Your code would then be:

map.computeIfAbsent(invoiceHeader.getInvoice_Date().toLocalDate(), x -> new ArrayList<>())
   .add(invoiceId);

If getInvoice_Date() returns a java.util.Date, then you can get the LocalDate value like this:

Instant invoiceInstant = invoiceHeader.getInvoice_Date().toInstant();
LocalDateTime invoiceDateTime = LocalDateTime.ofInstant(invoiceInstant, ZoneId.systemDefault());
LocalDate invoiceDate = invoiceDateTime.toLocalDate();

Combining the code above gives you:

map.computeIfAbsent(LocalDateTime.ofInstant(invoiceHeader.getInvoice_Date().toInstant(),
                                            ZoneId.systemDefault()).toLocalDate(),
                    x -> new ArrayList<>())
   .add(invoiceId);

Upvotes: 3

davidxxx
davidxxx

Reputation: 131324

Here you add/get date + time as key in the map. It will not work because you have to add the date without time if you want to be able to have the same key for same date but with different time.
Note that you should use LocalDateTime instead of Date that is a better designed API and that has the advantage to be immutable, which is advised for map keys.

With a few change you could do that :

LocalDate date = invoiceHeader.getInvoice_Date().toLocalDate();
if(map.containsKey(date)){
    map.get(date).add(invoiceId);        
}
else{    
    List<Integer> invoicesList = new ArrayList<>();
    invoicesList.add(invoiceId);
    map.put(date,invoicesList);
 }

With Map.computeIfAbsent() that provides a fluent API : you could simplify the whole logic such as :

LocalDate date = invoiceHeader.getInvoice_Date().toLocalDate();
map.computeIfAbsent(date, k-> new ArrayList<>()).add(invoiceId);

Upvotes: 2

Related Questions