我必须编写一个程序,显示Timeplan关于何时发送电子邮件。
用户正在输入开始日期,我必须显示一年的时间计划。 如何循环任务? 在此示例中,邮件应每8天发送一次。
if(recipient==0) {
System.out.println("send mail on this day:" +calendar.getTime());
calendar.add((GregorianCalendar.DAY_OF_YEAR),8);
return true;
}
我想将System.out.println
和calendar.add
任务循环到一年之后。
编辑:我还有另一个案例,它应该每16天发送一次电子邮件,但是当星期六或星期日,它应该在下一个星期一发送邮件。
我是这样做的,但现在我得到的日期超出了我的需要。
if(empfaenger==1)
{
for (Date d=startDate; d.before(endDate); d.setTime(d.getTime() + (1000 * 60 * 60 * 24 * 8)))
{
if(calendar.get(calendar.DAY_OF_WEEK)==1)
{
calendar.add((GregorianCalendar.DAY_OF_YEAR),1);
System.out.println("mail will be sent on this day:"+calendar.getTime());
calendar.add((GregorianCalendar.DAY_OF_YEAR), 16);
}
else if(calendar.get(calendar.DAY_OF_WEEK)==7)
{
calendar.add((GregorianCalendar.DAY_OF_YEAR), 2);
System.out.println("mail will be sent on this day:"+calendar.getTime());
calendar.add((GregorianCalendar.DAY_OF_YEAR),16);
}
else
{
System.out.println("mail will be sent on this day:"+calendar.getTime());
calendar.add((GregorianCalendar.DAY_OF_YEAR),16);
}
//System.out.println(calendar.getTime;)
}
}
答案 0 :(得分:1)
以下是使用java 8中的 java.time api的示例,它更易于理解和使用日历或日期类:
static void sendEveryEightDays(){
LocalDateTime timeToSendEmail= LocalDateTime.now();
LocalDateTime afterAYear = timeToSendEmail.plusYears(1);
while(timeToSendEmail.isBefore(afterAYear)){
System.out.println("SendTheEmail "+timeToSendEmail.toString());
timeToSendEmail=timeToSendEmail.plusDays(8);
}
}
如果您想考虑用户的时区,可以使用 ZonedDateTime 关闭 LocalDateTime :
static void sendEveryEightDays(ZoneId userTimeZone){
ZonedDateTime timeToSendEmail= ZonedDateTime.now(userTimeZone);
ZonedDateTime afterAYear = timeToSendEmail.plusYears(1);
while(timeToSendEmail.isBefore(afterAYear)){
System.out.println("SendTheEmail "+timeToSendEmail.toString());
timeToSendEmail=timeToSendEmail.plusDays(8);
}
}
答案 1 :(得分:0)
我想知道老师为什么还在教授旧API(Date
,Calendar
和SimpleDateFormat
),因为他们有lots of problems和design issues,他们& #39;被新API取代。 (Java 8于2014年发布,顺便说一下。)
无论如何,如果你有一个GregorianCalendar
,你可以将它转换为新的java.time
类,然后用它们完成。
首先,您可以使用日历创建Instant
:
Instant instant = Instant.ofEpochMilli(calendar.getTimeInMillis());
唯一的问题是,如果您创建Calendar
并设置日,月和年,它将具有当前时间(小时/分钟/秒),因此上面的Instant
将以UTC格式表示当前时间。如果可以,您可以将此瞬间转换为您的时区:
ZoneId zone = ZoneId.of("America/Sao_Paulo");
ZonedDateTime start = instant.atZone(zone);
我使用America/Sao_Paulo
,但您可以更改为对您的系统有意义的时区。 API使用IANA timezones names(始终采用Region/City
格式,如America/Sao_Paulo
或Europe/Berlin
)。
避免使用3个字母的缩写(例如CST
或PST
),因为它们是ambiguous and not standard。
您可以致电ZoneId.getAvailableZoneIds()
获取可用时区列表(并选择最适合您系统的时区)。如果需要,您也可以使用系统的默认设置(ZoneId.systemDefault()
),但请注意,即使在运行时也可以在不事先通知的情况下进行更改,因此最好指定您的时区#&# 39;重新使用。如果要使用UTC中的日期,可以使用内置常量ZoneOffset.UTC
。
上面的代码会创建一个ZonedDateTime
,其日历的日期和时间会调整到指定的时区。只是提醒一下,如果你这样做:
Calendar calendar = new GregorianCalendar();
calendar.set(2017, 7, 12);
日期相当于 8月12日 th 2017 (因为Calendar
API中的月份从零开始,因此第7个月是8月),并且时间将是创建日历的当前时间。
如果您想指定小时,您可以选择一些小时来调整它:
// change the hour/minute/second to 10:20:45
start = start.with(LocalTime.of(10, 20, 45));
// change just the hour to 10
start = start.withHour(10);
// set to start of the day
start = start.toLocalDate().atStartOfDay(zone);
通过此,您可以相应地更改时间(以及日期)字段。查看javadoc和Oracle's tutorial,查看所有可用选项。方法atStartOfDay
更好,因为它会处理夏令时变化(取决于夏令时的变化,这一天可以从凌晨1点而不是午夜开始,这个方法会处理所有细节。)
如果您不想依赖Calendar
,还可以直接创建日期:
// creating August 12th 2017, at 10:00
start = ZonedDateTime.of(2017, 8, 12, 10, 0, 0, 0, zone);
请注意,8月是第8个月(旧API的最佳和最明显的改进之一)。
现在你有了开始日期,你可以循环一整年,并根据你的规则检查日期。我是使用每16天发送一次电子邮件的示例,如果是周末则调整到下一个星期一:
ZonedDateTime d = start;
// ends in 1 year - this method already takes care of leap years
ZonedDateTime end = start.plusYears(1);
while (end.isAfter(d)) {
d = d.plusDays(16);
if (d.getDayOfWeek() == DayOfWeek.SUNDAY || d.getDayOfWeek() == DayOfWeek.SATURDAY) {
// weekend, adjust to next monday
d = d.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
}
// send email
}
如果您使用的是Java< = 7,则可以使用ThreeTen Backport,这是Java 8新日期/时间类的绝佳后端。
与Java 8的唯一区别是包名称(在Java 8中为java.time
而在ThreeTen Backport(或Android的ThreeTenABP中)为org.threeten.bp
),但类和方法< strong>名称是相同的。
正如@BasilBourque在评论中提醒我的那样,您还可以使用GregorianCalendar
方法将ZonedDateTime
转换为toZonedDateTime()
(这将使用日历的时区 - 通常系统的默认设置,如果你没有设置它)。您也可以使用Instant
方法将其转换为toInstant()
。唯一的限制是这些方法仅在Java 8中可用(因此,如果您使用的是ThreeTen Backport,只需使用上面描述的方式)。