0

I have a string in data format, apr 17,2016.

For instance, I would like to go back 1 day, so I would like to get apr 16,2016.

How can I do that?

Please note, it could be mar 1,2016 as well so the replacement at index cannot work.

8
  • 6
    You parse the value as a date/time (e.g. using java.time) and then you use the appropriate date manipulation methods. You don't try to do it all with string operations. Commented Apr 6, 2017 at 18:14
  • I got this as a String, so I HAVE to use it. (Test automation purpose, not development. It was not clear, but doesn't matter, my question was accurate) Commented Apr 6, 2017 at 18:29
  • 2
    You have to use it, sure. That's what the "You parse the value" part was about. That doesn't mean you have to do everything with string operations. (That's what both of the current answers do, and it's a really bad idea. Why reinvent the wheel when there are multiple ways of parsing dates in Java already?) Commented Apr 6, 2017 at 18:31
  • I need to check this out, I'm not familiar with java.time. Thanks. You think it was easier than String operations? I always will get string and I need to parse the value and vica versa to get a string at the end as well. It is not to expensive? Commented Apr 6, 2017 at 18:36
  • 1
    Well do you have well-defined performance constraints? You haven't mentioned those yet. I would definitely start with the simple, clear code that tries to do work in the appropriate domain - and "get the previous day" is definitely work in the date/time domain rather than the string domain. Commented Apr 6, 2017 at 18:37

7 Answers 7

2

tl;dr

LocalDate.parse ( 
    "apr 17,2016" , 
    DateTimeFormatter.ofPattern ( "MMM dd,uuuu" ).withLocale( locale ) 
)

Using java.time

The modern way is with the java.time classes.

You do not specify the locale or human language intended for your input strings. The initial lowercase letter in the month name abbreviation is not appropriate to US English. So I tried all the locales provided with Java 8 Update 121, ignoring any parsing attempts that failed with an exception.

Note how we call DateTimeFormatter::withLocale inside the loop. Locale determines (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, separators, and such.

You can do date-time math to get the previous day by calling LocalDate::minusDays.

String input = "apr 17,2016";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "MMM dd,uuuu" );

for ( Locale locale : Locale.getAvailableLocales ( ) ) {
    try {
        LocalDate ld = LocalDate.parse ( input, f.withLocale ( locale ) );
        System.out.println ( locale.getDisplayName ( ) + " → " + ld + " | day before: " + ld.minusDays ( 1 ) );
    } catch ( java.time.format.DateTimeParseException e ) {
        // Swallow this expected exception. No code needed here.
    }
}
System.out.println ( "Done." );

Nineteen worked.

Italian → 2016-04-17 | day before: 2016-04-16
Swedish (Sweden) → 2016-04-17 | day before: 2016-04-16
Slovak → 2016-04-17 | day before: 2016-04-16
Estonian → 2016-04-17 | day before: 2016-04-16
Swedish → 2016-04-17 | day before: 2016-04-16
Serbian (Latin,Bosnia and Herzegovina) → 2016-04-17 | day before: 2016-04-16
Serbian (Latin,Montenegro) → 2016-04-17 | day before: 2016-04-16
Norwegian (Norway,Nynorsk) → 2016-04-17 | day before: 2016-04-16
Estonian (Estonia) → 2016-04-17 | day before: 2016-04-16
Serbian (Latin) → 2016-04-17 | day before: 2016-04-16
Dutch → 2016-04-17 | day before: 2016-04-16
Norwegian (Norway) → 2016-04-17 | day before: 2016-04-16
Dutch (Netherlands) → 2016-04-17 | day before: 2016-04-16
Italian (Switzerland) → 2016-04-17 | day before: 2016-04-16
Slovak (Slovakia) → 2016-04-17 | day before: 2016-04-16
Italian (Italy) → 2016-04-17 | day before: 2016-04-16
Dutch (Belgium) → 2016-04-17 | day before: 2016-04-16
Norwegian → 2016-04-17 | day before: 2016-04-16
Serbian (Latin,Serbia) → 2016-04-17 | day before: 2016-04-16
Done.

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Sign up to request clarification or add additional context in comments.

Comments

2

You can use Java 8 for this.

Just convert to LocalDate. It has flexible API for many reasons.

Here is code snippet:

public static void main(String[] args) throws ParseException {
    String dateStr = "apr 17,2016";
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd,uuuu");

    // convert to local date
    LocalDate localDate = LocalDate.parse(dateStr, formatter.withLocale(Locale.ITALIAN));
    System.out.println("START DATE:\n" + localDate);

    // use all power of new java.time
    LocalDate oneDayBefore = localDate.minusDays(1);
    LocalDate oneMonthBefore = localDate.minusMonths(1);
    LocalDate oneWeekBefore = localDate.minusWeeks(1);
    LocalDate oneYearBefore = localDate.minusYears(1);

    System.out.println("RESULTS:");
    System.out.println(oneDayBefore);
    System.out.println(oneMonthBefore);
    System.out.println(oneWeekBefore);
    System.out.println(oneYearBefore);
}

Output:

START DATE:
2016-04-17
RESULTS:
2016-04-16
2016-03-17
2016-04-10
2015-04-17

Now you need to print local date as a string.

Here is example:

    // use Java 8 features
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MMM dd,yyyy");
    String dt = dtf.format(oneDayBefore);
    System.out.println(dt);

Output:

Apr 16,2016

5 Comments

If you're using LocalDate - which I agree is the right way to go - don't use SimpleDateFormat... use DateTimeFormatter... that's what it's there for.
As Jon Skeet commented, you are mixing incompatible classes. The java.time classes supplant the old legacy date-time classes. Use just the java.time classes. Also, you are overworking the problem. Use just LocalDate without going to a date-time (Instant).
@JonSkeet Thank you for a recommendation. Answer is updated.
Hooray - much better. Finally an answer I can fully support :) (Admittedly, I'm not sure about setting the locale to Italian - but at least it's explicit. Hopefully the OP will set it to whatever they actually want.)
Thank you all for your help! Please note, I accepted one solution, but I'm sure, the others is working well. I need a simple solution and I found it helpful. Thanks again!
1

**Note : you should use a date class instead of strings, but there are better classes available than the ones I used here. ** I will edit this answer to reflect this, but you should look below at solutions that are more appropriate for current Java versions and to the precision (day instead of millisecond) requested here.

The most robust way is to convert your string into a date class, manipulate the date, then reformat it back. The conversion in each direction can be done with the SimpleDateFormat class (Api docs) and the changing of the date is easily done with the Calendar class (API docs)

This runs and takes the date from the argument and outputs the format with one day subtracted, as you asked.

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Calendar;

public class DateSubtractExample{
    public static String backOneDay(String inDate){
      SimpleDateFormat formatter = new SimpleDateFormat("MMM dd,yyyy");
      try{
          // turn your string into a date (if formatting is right)
          Date date1 = formatter.parse(inDate);
          // make a calendar, set it to the date, and subtract one day.
          Calendar cal = Calendar.getInstance();
          cal.setTime(date1);
          cal.add(Calendar.DATE,-1);
          // convert date back to input format. 
          return formatter.format(cal.getTime());
        }
        catch (ParseException bad){
                bad.printStackTrace();
                return "UNREADABLE DATE "+inDate+":"+bad;

        }
    }

    public static void main(String[] args) throws ParseException{
       System.out.println(DateSubtractExample.backOneDay(args[0]));
    }
}

2 Comments

This is definitely better than raw string manipulation, but I'd recommend using java.time where possible these days.
In support of @JonSkeet’s comment, a Date is a point in time with millisecond precision, this is basically not what you need. LocalDate in java.time much better reflects (models) what you’re after (there are a couple of other answers using it).
0
public String getPreviousDate(String oldDate) {
    String[] parts1 = oldDate.split(" "); // split the oldDate around " "
    String[] parts2 = parts1[1].split(","); // split the second part of oldDate around ","

    String month = parts1[0];
    int day = Integer.parseInt(parts2[0]);
    int year = Integer.parseInt(parts2[1]);
    ...
    return newDate;
}

1 Comment

You appear to be omitting rather a lot in the "..." here... like working out what month it is, and what month should be in the result. I'd also strongly advise against writing your own date parser, which is effectively what you're doing.
0

This will work as per your requirement please try this, tested program so no need to worry

import java.text.SimpleDateFormat;  
import java.util.*;

public class DateExample{
    public static void main(String args[]) throws Exception {

        String date = "apr 16,2016";
    SimpleDateFormat formatter=new SimpleDateFormat("MMM dd,yyyy");  

    Date dateFormated =formatter.parse(date);  
    System.out.println(dateFormated);

    GregorianCalendar cal = new GregorianCalendar();
    cal.setTime(dateFormated);
    cal.add(Calendar.DATE, -1);

        Date newDate = cal.getTime();
    String stringDate = formatter.format(newDate);
        System.out.println(stringDate);
    }

}

1 Comment

Note that this will use the system default locale, which may well not be a good idea - if the values are known to be in a particular locale, that's what should be used.
0

I feel I am not clear in the question you are asking. I saw two questions, one related to replace part of string and another about date. I assume you question is about the date. So I tried to reply your question thinking you want to decrease the current date by one day.

For this you can use Calendar interface.

Calendar cal = Calendar.getInstance();
cal.setTime(myDate);
cal.add(Calendar.DAY_OF_YEAR,-1);
Date oneDayBefore= cal.getTime();

Comments

-1

So, Id use string.split(","). Example Code :

String date="apr 1,2016";
String[] parts=date.split(",");
String month_and_day=parts[0];
String year=parts[1];
String[] parts_of_month_and_day=month_and_day.split(" ");
String month=parts_of_month_and_day[0];
String day=parts_of_month_and_day[1];
int m;
int d;
int y;
y=Integer.parseInt(year);
d=Integer.parseInt(day);
String[] months=new String[] {"jan","feb","mar","apr","may","jun","jul","aug","sep","okt","nov","dez"};
for (int i=0; i < 12 /*length of months*/; i++) {
     if (months[i].equals(month)) {
         m=i;
     }
}

2 Comments

Why would you use String.split instead of using any of the various ways of parsing a date? You seem happy enough to use Integer.parseInt - so why not the date parsing facilities as well?
Note that you have only done half the work, too. You've written some parsing code, but nothing around subtracting a day and reformatting.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.