This question already has an answer here:
-
Does Java support Julian calendar?
4 answers
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);
}
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);
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.