【发布时间】:2013-04-26 03:11:13
【问题描述】:
简单的问题,但令人惊讶的是,谷歌对此几乎没有。我有今年 1 月 1 日的number of days。如何在 Java 中将其转换为 date?
【问题讨论】:
简单的问题,但令人惊讶的是,谷歌对此几乎没有。我有今年 1 月 1 日的number of days。如何在 Java 中将其转换为 date?
【问题讨论】:
Year.of( 2017 )
.atDay( 159 )
2017-06-08
…或当前年份…
Year.now( ZoneId.of( "America/Montreal" ) )
.atDay( 159 )
2018-06-08
换个方向,从日期到一年中的某一天。
LocalDate.now( ZoneId.of( "America/Montreal" )
.getDayOfYear()
159
处理日期时间的现代方法是使用 java.time 类。麻烦的旧日期时间包。麻烦的旧日期时间类,例如 java.util.Date、java.util.Calendar 和 java.text.SimpleTextFormat,现在是 legacy,被 java.time 类所取代。
Year 类显然代表一年。要获取当前年份,我们需要当前日期。
时区对于确定日期和年份至关重要。对于任何给定的时刻,日期在全球范围内因区域而异。例如,Paris France 中午夜后几分钟是新的一天,而 Montréal Québec 中仍然是“昨天”。同样,元旦在巴黎午夜过后几分钟是新的一年,而在魁北克仍然是“去年”。
以continent/region 的格式指定proper time zone name,例如America/Montreal、Africa/Casablanca 或Pacific/Auckland。切勿使用 3-4 个字母的缩写,例如 EST 或 IST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。
ZoneId z = ZoneId.of( "America/Montreal" );
Year year = Year.now( z );
如果您有特定的年份,请传递年份编号。
Year year = Year.of( 2017 );
Year 类包含一个方法 atDay,用于在传递 Leap Year 中从 1 到 365 或 366 的年份数字时生成 LocalDate。 LocalDate 类表示没有时间和时区的仅日期值。
LocalDate localDate = year.atDay( 159 );
反过来,您可以致电LocalDate::getDayOfYear 询问LocalDate 的日期。
int dayOfYear = localDate.getDayOfYear() ;
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。
【讨论】:
使用日历进行日期运算
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, 2013);
c.set(Calendar.MONTH, Calendar.JANUARY);
c.set(Calendar.DATE, 1);
c.set(Calendar.HOUR, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
c.add(Calendar.DATE, numberOfDays);
Date date = c.getTime();
请注意,由于 DST(夏令时),不同地区的结果可能会有所不同。上面的示例使用默认语言环境。
【讨论】:
java.util.Date、java.util.Calendar 和 java.text.SimpleDateFormat 现在是 legacy,被 Java 8 中内置的 java.time 类所取代,之后。见Tutorial by Oracle。
我发现JodaTime 在日期处理方面使用起来非常优雅。有了它,你可以这样做:
DateTime date = new DateTime().withDayOfYear(dayOfYear);
【讨论】:
您可以简单地使用SimpleDateFormat 将String 转换为Date。模式D可以用来表示一年中的天数。
前提是你有
int numberOfDays = 42; // Arbitrary number.
那么这个计算自 1970 年 1 月 1 日以来的天数 (the Epoch)
Date date = new SimpleDateFormat("D").parse(String.valueOf(numberOfDays));
或者,这个计算自当年 1 月 1 日以来的天数。
Date date = new SimpleDateFormat("D yyyy").parse(numberOfDays + " " + Calendar.getInstance().get(Calendar.YEAR));
【讨论】:
如果您是 Android 开发人员并使用 JodaTime,这就是您在 java 8 中获得等价物的方式。
LocalDate.ofYearDay("2020", 255).getDayOfWeek().getValue()
使用这个是因为 ofYearDay 仅在 Android >= 26 以上才支持;
MutableDateTime mutableDateTime1 = new MutableDateTime();
mutableDateTime1.setYear("2020");
mutableDateTime1.setDayOfYear(255);
LocalDate.fromDateFields(mutableDateTime1.toDate()).getDayOfWeek();
【讨论】:
GregorianCalendar 和simpleDateFormat:int days = 20;
GregorianCalendar dayCountofYear = new GregorianCalendar(2020,Calendar.JANUARY, 1);
dayCountofYear.add(Calendar.DAY_OF_YEAR, days);
System.out.println("GregorianCalendar: "+ dateFormat.format(dayCountofYear.getTime()));
上面的逻辑可以简化为如下的函数调用:
Date nextDate = addDaysToDate("01/01/2020", 20);
System.out.println("After Adding Number of Days:"+nextDate); // O/P:21/01/2020
完整示例:
public class DateHelper {
public static void main(String[] args) throws ParseException {
int days = 20;
String initialDay = "01/01/2020";
Date nextDate = addDaysToDate(initialDay, days);
System.out.println("After Adding Number of Days:"+nextDate);
/*Date firstDate = DateHelper.parseDate(initialDay, formatStr);
int daysBetween = getDaysBetween(firstDate, nextDate);
System.out.println(days + " - Days Between - "+daysBetween);*/
}
static String formatStr = "dd/MM/yyyy";
static DateFormat dateFormat = new SimpleDateFormat(formatStr);
static DateFormat reverseDateFormat = new SimpleDateFormat("yyyy/MM/dd");
public static Date addDaysToDate(String specificDate, int daysCount) throws ParseException {
Date date = dateFormat.parse(specificDate);
GregorianCalendar gregCal = (GregorianCalendar) GregorianCalendar.getInstance(); // Current Date
gregCal.setTime(date); // Change the Date to Provided One
gregCal.add(Calendar.DAY_OF_YEAR, daysCount);
Date time = gregCal.getTime();
ZonedDateTime zdt = gregCal.toZonedDateTime();
System.out.println("GregorianCalendar DayofWeek: "+ zdt.getDayOfWeek());
return time;
}
public static String addDaysToDateStr(String specificDate, int daysCount) throws ParseException {
String format = dateFormat.format( addDaysToDate(specificDate, daysCount) );
System.out.println("GregorianCalendar [To a Date added Number of days leads to New Date]: "+ format);
return format;
}
public static Date parseDate(String aSource, String formatStr) throws ParseException {
DateFormat dateFormat = new SimpleDateFormat(formatStr);
dateFormat.setLenient(false);
return dateFormat.parse(aSource);
}
public static String formatDate(Date aDate, String formatStr, Calendar calendar) {
DateFormat dateFormat = new SimpleDateFormat(formatStr);
dateFormat.setLenient(false);
dateFormat.setCalendar(calendar);
return dateFormat.format(aDate);
}
public static String formatDate(Date aDate, String formatStr) {
DateFormat dateFormat = new SimpleDateFormat( formatStr );
//dateFormat.setCalendar(Calendar.getInstance(TimeZone.getTimeZone("UTF")));
return dateFormat.format(aDate);
}
}
【讨论】:
java.util.Date、java.util.Calendar 和 java.text.SimpleDateFormat 等存在严重缺陷的日期时间类现在是 legacy,被 Java 8 及更高版本中内置的 java.time 类所取代.建议在 2020 年使用它们是糟糕的建议。
SimpleDateFormat 是出了名的麻烦,GregorianCalendar 设计也很糟糕。两者都已经过时了。谁需要在 2020 年使用这些课程得到答案?恕我直言,世界上没有人。
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, 2016);
c.set(Calendar.MONTH, 8);
c.set(Calendar.DAY_OF_YEAR, 244);
c.set(Calendar.HOUR, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
Date date = c.getTime();
【讨论】: