我需要创建一个程序,从.csv
文件中读取日期并对其进行转换,以便添加13天。我已经这样做但不知何故它没有按照希望添加以下日期。它也超过30天,例如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);
}
答案 0 :(得分:3)
您要从actDay
两次减去13,先是actDay-=13
,另一次是if(actDay - 13 < 1)
。在if
块内,然后将小于14的值添加到每月的天数中,从而导致月中溢出。
如果您只想从给定日期减去13天,则应使用c.set(Calendar.DAY_OF_MONTH,actDay-13)
。这将在Calendar
对象内正确处理减法,然后您可以使用
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);
答案 1 :(得分:2)
关于算法中的一些错误,请参阅HeikkiMäenpää的答案。我还看到了另一个错误,即错误的模式“yyyy-mm-dd”,其中“mm”代表分钟(使用“MM”几个月)。
但总的来说,你似乎试图重新发明轮子。即使旧的java.util.Calendar
- API也有从gregorian到julian日历日期转换的内置方式,请参阅我的解决方案,该解决方案即使在过去的任何日期也适用于切换。
您的解决方案仅适用于格里高利和朱利安历法之间的距离为13天的日期(过去不是这样,在教皇格雷戈尔改革时,只有10天被切断)。 强>
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);
}
正如您所看到的,旧的API函数甚至会强制您将时区设置为固定的偏移量,以避免任何可能的时区混乱。这是必要的,因为java.util.Calendar
和java.util.Date
不是真正的日历日期,而是瞬间/时刻。
旁注:
我写了一个时间库(Time4J),如果它是格里高利或朱利安(甚至是瑞典语),它甚至可以处理任何historic date平等,在历史性年份开始时相等(在大多数情况下)不是一月的第一天!)等。也许这对你的问题来说太过分了,但我提到了你真正希望以真实的历史日历日期运作的情况。