1

I need to create a program that reads dates from a .csv file and convert it so that 13 days are added. I already did that but somehow it does not add the following dates as wished. It also goes over 30 days, which is not supposed to happen for example 2001-12-42.

public static void main(String[] args) throws FileNotFoundException, ParseException {
    File fread = new File("src/daten-greg.csv");
    File fwrite = new File("src/daten-jul.csv");

    Scanner s = new Scanner(fread);
    PrintStream print = new PrintStream(fwrite);

    while(s.hasNext()) {
        String[] line = s.nextLine().split(" ");
        print.println(String.join(" ", Convert(line)));
    }

    s.close();
    print.close();
}

private static String[] Convert(String[] value) throws ParseException {
    for (int i = 0; i < value.length; i+=1)
        value[i] = ToJulianisch(value[i]);

    return value;
}

private static String ToJulianisch(String date) throws ParseException {
    SimpleDateFormat  sdf = new SimpleDateFormat("yyyy-mm-dd");
    Date d = sdf.parse(date);


    Calendar c = Calendar.getInstance();
    c.setTime(d);

    int actDay = c.get(Calendar.DAY_OF_MONTH);
    int actMonth = c.get(Calendar.MONTH) + 1 ;
    int actYear = c.get(Calendar.YEAR);
    actDay -= 13;

    if(actDay - 13 < 1) {
        actMonth -= 1;
        if(actMonth < 1) {
            actMonth = 12;
            actYear -= 1;
        }   
        Calendar k = Calendar.getInstance();
        k.set(Calendar.YEAR, actYear);
        k.set(Calendar.MONTH, actMonth - 1);
        actDay = k.getActualMaximum(Calendar.DAY_OF_MONTH) + actDay;
    }

    return String.format("%s-%s-%s", actYear, actMonth, actDay);
}
  • As an aside, you could have posted the code of `ToJulianisch` and maybe a few example inputs/outputs for a more readable question (i.e. a [mcve]). Posting your entire class code gives the impression that you haven't done the legwork to pinpoint the misbehaving method. – Haem Oct 24 '17 at 10:19
  • FYI, the terribly troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Nov 02 '18 at 05:09

2 Answers2

3

You are subtracting 13 from actDay twice, first in actDay-=13 and again for if(actDay - 13 < 1). Inside the if block, you then add the value which is less than 14 to the number of days per month, resulting in overflowing the day of month.

If you simply want to subtract 13 days from the given date, you should use c.set(Calendar.DAY_OF_MONTH,actDay-13). This will handle the subtraction correctly inside the Calendar object and you can then use

actDay = c.get(Calendar.DAY_OF_MONTH);
int actMonth = c.get(Calendar.MONTH) + 1 ;
int actYear = c.get(Calendar.YEAR);
return String.format("%s-%s-%s", actYear, actMonth, actDay);
Haem
  • 929
  • 6
  • 15
  • 31
2

About some mistakes in your algorithm, see the answer of Heikki Mäenpää. I have also seen another mistake, namely a wrong pattern "yyyy-mm-dd" where "mm" stands for minutes (use "MM" for months).

But in general, you seem to try to reinvent the wheel. Even the old java.util.Calendar-API has a built-in way for the transformation from a gregorian to a julian calendar date, see my solution which is valid even for any date in the past with respect to cutover.

Your solution is only valid for dates where the distance between gregorian and julian calendar is 13 days (which is not true in the past, at the time of Pope Gregor's reform, there were only 10 days cut off).

public static void main(String[] args) throws ParseException {
  String input = "2017-10-24";
  System.out.println("Old API => " + toJulianisch(input)); // 2017-10-11
}

private static String toJulianisch(String date) throws ParseException {
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
  GregorianCalendar gcal = new GregorianCalendar();
  gcal.setTimeZone(TimeZone.getTimeZone("GMT"));
  gcal.setGregorianChange(new Date(Long.MIN_VALUE));
  sdf.setCalendar(gcal);
  Date d = sdf.parse(date);

  gcal.setGregorianChange(new Date(Long.MAX_VALUE));
  gcal.setTime(d);
  return sdf.format(d);
}

As you can see, the old API-stuff even forces you to set the timezone to a fixed offset to avoid any possible timezone clutter. This is necessary because java.util.Calendar and java.util.Date are not real calendar dates but instants/moments.

Side notice:

I have written a time library (Time4J) which can even handle any historic date equal if it was gregorian or julian (or even swedish), equal when the historic year started (was in most cases not the first of January!) etc. Maybe it is overkill for your problem but I mention it for the case you really want to operate with true historic calendar dates.

Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126
  • It‘s a code I have to write for school, the task is given that‘s why I have to put a difference of 13 days otherwise your answer would have been the most helpful –  Oct 24 '17 at 11:32
  • @U.Gue Well, 13 days are only okay for the period between the years 1901 and 2099. – Meno Hochschild Oct 24 '17 at 11:36
  • That‘s ok, it‘s what the task states as well –  Oct 24 '17 at 12:17