Не используйте Date
или Calendar
, API java.time
более способен достичь того, что вы хотите.
Глядя на это ...
Date date = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);
//creating a new calendar with all of the data
Calendar cal = Calendar.getInstance();
cal.set(year, month, day, hours, mins, seconds);
Вы создаете новое время, основываясь на часах / минутах / секундах, но, что меня беспокоит, так это то, что происходит, если время меньше, чем сейчас? Это может быть проблема, с которой вы столкнулись.
Итак, вы можете захотеть проверить, указано ли время до или после текущего времени, и соответственно изменить день - при условии, что вы хотите использовать абсолютное время (ie создайте таймер, который отсчитывает время до 18:00)
Это ...
Duration countingDown = Duration.between(Instant.now(), userInputCountDown);
мне тоже кажется неправильным, так как userInputCountDown
должен быть в будущее
В следующем примере используется несколько иной подход, поскольку он создает «таймер», который создаст цель в будущем (на основе входных данных) из текущего времени (добавление часов, минут и секунд). ) и использовать его как опорную точку для обратного отсчета.
Итак, вы можете сказать, например, «создать 1-часовой» таймер.
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTextField targetHours;
private JTextField targetMins;
private JTextField targetSeconds;
private Instant futureTime;
private Timer timer;
private JLabel countDown;
public TestPane() {
setLayout(new GridBagLayout());
targetHours = new JTextField("00", 2);
targetMins = new JTextField("00", 2);
targetSeconds = new JTextField("00", 2);
JPanel targetPane = new JPanel(new GridBagLayout());
targetPane.add(targetHours);
targetPane.add(new JLabel(":"));
targetPane.add(targetMins);
targetPane.add(new JLabel(":"));
targetPane.add(targetSeconds);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.insets = new Insets(8, 8, 8, 8);
add(targetPane, gbc);
JButton btn = new JButton("Start");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
futureTime = LocalDateTime.now()
.plusHours(Long.parseLong(targetHours.getText()))
.plusMinutes(Long.parseLong(targetMins.getText()))
.plusSeconds(Long.parseLong(targetSeconds.getText()))
.atZone(ZoneId.systemDefault()).toInstant();
if (timer != null) {
timer.stop();
}
countDown.setText("---");
timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Duration duration = Duration.between(Instant.now(), futureTime);
if (duration.isNegative()) {
timer.stop();
timer = null;
countDown.setText("00:00:00");
} else {
String formatted = String.format("%02d:%02d:%02d", duration.toHours(), duration.toMinutesPart(), duration.toSecondsPart());
countDown.setText(formatted);
}
}
});
timer.start();
}
});
add(btn, gbc);
countDown = new JLabel("---");
add(countDown, gbc);
}
}
}
WARNING - Я не проверяю входные данные, поэтому вам нужно быть осторожным.
Если вместо этого вы хотите выполнить обратный отсчет до определенного момента времени (ie отсчет с настоящего времени до 18:00). ), тогда вам нужно будет использовать цепочку LocalDateTime#withHour(Long)#withMinute(Long)#withSecond(Long)
. Но, будьте осторожны, вам придется проверить, наступило ли время в будущем или прошлом, и предпринять соответствующие действия, потому что, если вы хотите отсчитывать время до 6 вечера, но это 7 вечера ... что это на самом деле означает: /?