0

I have an old string value as below

2018-03-21 00:00:00.0 

I would like to change the time to 23:18:19 but remain the date as 2018-03-21.

So the new value will be 2018-03-21 23:18:19.

This is what I have tried

System.out.println("date is " + date);   // 2018-03-21 00:00:00.0 

String[] parts = date.split(" ");  
System.out.println("Date: " + parts[0]);   // 2018-03-21
System.out.println("Time is : " + parts[1]); // 00:00:00.0 

String replaceString=parts[1].replace(?,'23:18:19');
System.out.println("Value is : " +  replaceString); //2018-03-21 23:18:19

What should I put in the ? ?

Iamd
  • 33
  • 3
Cyndi
  • 59
  • 1
  • 9

4 Answers4

3

Using a DateTimeFormatter is probably the nicest way to do this. No nasty string manipulation involved at all.

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .append(DateTimeFormatter.ISO_LOCAL_DATE)
    .appendLiteral(' ')
    .append(DateTimeFormatter.ISO_LOCAL_TIME)
    .toFormatter();

LocalDateTime oldTime = LocalDateTime.parse("2018-03-21 00:00:00.0", formatter);
LocalDateTime newTime = oldTime.withHour(23).withMinute(18).withSecond(19).withNano(0);

System.out.println(newTime.format(formatter));

Output: 2018-03-21 23:18:19

Michael
  • 41,989
  • 11
  • 82
  • 128
3

Using the same formatter suggested by Michael, but a little bit shorter code to set the time:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .append(DateTimeFormatter.ISO_LOCAL_DATE)
    .appendLiteral(' ')
    .append(DateTimeFormatter.ISO_LOCAL_TIME)
    .toFormatter();

LocalDateTime dt = LocalDate.parse("2018-03-21 00:00:00.0", formatter)
    .atTime(LocalTime.of(23, 18, 19));

System.out.println(dt.format(formatter));

Parsing to a LocalDate, you ignore the part you don't want, which is the 00:00:00 part. Then you set the time you want in one step, using atTime. This is a little bit more efficient than Michael's answer because every call to a withXXX method creates another object. Not sure if that'll make a big difference in your code, though.

If you have a String instead of the time numerical values, you can use LocalTime.parse("23:18:19") instead of LocalTime.of.

You can see the code running at: https://ideone.com/STduWa

Using the java.time classes is better than just replacing the string, because it also validates the input, such as numerical values outside the range (if the input is "99:99:99", replace doesn't validate it, while the java.time classes do, etc).

Iamd
  • 33
  • 3
  • "This is a little bit more efficient" premature optimisation alert – Michael Mar 25 '18 at 14:49
  • @Michael I also tend to avoid premature optimization, but in this specific case, I disagree. Your solution has 4 method calls, creating 4 `LocalDateTime` instances - 3 will be discarded and garbage collected, while lamd's code uses 1 method call and creates 1 object that'll be used and won't be GC'ed. Reducing method calls and objects created to 25% of the total is a considerable improvement - it might look superfluous in such a small code, and we can't really know the real-world usage scenarios for this, so it's impossible to know for sure it it's worth or it'll make any difference >>> – whatever Mar 26 '18 at 18:37
  • >>> but anyway, if I have 2 options, one of them has 1/4 of method calls and objects created, and both get the same result, I'd choose lamd's answer. It also has the nice advantage - and that's a little bit opiniated, but that's my opinion anyway - of being more clear and readable - and also more flexible, as you can use it with numerical values or a String (and the OP suggests that the string `23:18:19` is the input), while yours requires a manual parse of the string to get the numerical values, and then use those values in the `withXXX` methods. – whatever Mar 26 '18 at 18:37
  • @whatever three superfluous instances?? phew, it's a good job I have a pentium II! – Michael Mar 26 '18 at 18:57
  • @Michael English isn't my native language, so maybe I used the word "superfluous" in a wrong way. I wasn't talking about the instances. What I meant is that the code "optimization" in lamd's answer *might* look unnecessary and *seems* to be a case premature optimization (because the code is small and we don't know the real world usage to be sure if it's worth doing it), **but** I'd choose lamd's code instead of yours. Hope it's clear now. Your answer is also good, btw. – whatever Mar 26 '18 at 19:02
  • @whatever You used superfluous correctly. I'd choose his as well, because it's slightly easier to read. Readability and maintainability should be everyone's top concern. Suggesting that it's "slightly more efficient" is ridiculous without even profiling it. It's also irrelevant unless you've proven that it's a performance bottleneck. 999 times out of 1000, it's not going to be. – Michael Mar 26 '18 at 19:13
1

I have not tested this code but something like this should work..

Calendar mydate = new GregorianCalendar();
String dateString = "2018-03-21 00:00:00.0";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S, , Locale.ENGLISH);
Date thedate = LocalDate.parse(dateString, formatter); // As suggested by Michael
//LocalDate thedate = LocalDate.parse(dateString, formatter);
mydate.setTime(thedate);

Then set what you want to set with

mydate.set(Calendar.HOUR_OF_DAY,"23"));
mydate.set(Calendar.MINUTE,"18");
mydate.set(Calendar.SECOND,"19");
Manvi
  • 1,136
  • 2
  • 18
  • 41
  • 3
    `setTime` takes a `Date`, not a `LocalDate`. You're mixing `java.util` and `java.time` classes. – Michael Mar 24 '18 at 13:37
0
public static String test(){

    String date = "2018-03-21 00:00:00.0";

    System.out.println("date is " + date);   // 2018-03-21 00:00:00.0

    String[] parts = date.split(" ");
    System.out.println("Date: " + parts[0]);   // 2018-03-21
    System.out.println("Time is : " + parts[1]); // 00:00:00.0

    String replaceString=date.replace(parts[1],"23:18:19");
    System.out.println("Value is : " +  replaceString); //2018-03-21 00:00:00.0
    return replaceString;
}
alex440
  • 1,647
  • 3
  • 20
  • 35