I know this should be simple, but I can't find anything on the internet.
Given some conditions, I want to get the next Date when they will be met. For example, if conditions are minute = 01 and second = 30 and now the time is 15:58:00, the function should return today at 16:01:30. How can I accomplish this in Java?
I need to be able to set conditions of, at least, seconds, minutes and hours, but I would like to have the possibility to set one condition to any value (like the example above, that doesn't specify an hour).
Thanks and sorry for my bad English.
EDIT:
I see there's something that might need clarification: I want to get a Date (or whatever) always after the current time that meets conditions. Also, this is for a Minecraft Spigot server, maybe this information can help.
You could use streams for this:
Optional<LocalDateTime> firstMatch =
Stream.iterate(
LocalDateTime.now(),
ldt -> ldt.plusSeconds(1L))
.filter(
// Insert your condition here
ldt -> ldt.getSecond() == 0)
.findFirst();
What this code does is take the current LocalDateTime and use it to generate a stream of LocalDateTime objects (advancing the time by 1 second each time). Once it encounters a LocalDateTime that matches the provided condition, it returns this objects and terminates the stream.
Keep in mind that using this approach will generate a lot of objects if it takes a while for the condition to become true, so it is not very efficient.
If you want to strip the nanoseconds replace LocalDateTime.now() by LocalDateTime.now().withNano(0).
You can use LocalDateTime#plus... to add duration to get the updated time.
Demo:
import java.time.LocalDateTime;
import java.time.LocalTime;
public class Main {
public static void main(String[] args) {
String strTime = "15:58:00";
LocalTime time = LocalTime.parse(strTime);
// Today at the specified time
LocalDateTime today = LocalDateTime.now().with(time);
System.out.println(today);
// Today with the added minutes and seconds
LocalDateTime updated = today.plusMinutes(1).plusSeconds(30);
System.out.println(updated);
}
}
Output:
2021-02-23T15:58
2021-02-23T15:59:30
If you want to switch to a different time, you can use LocalDateTime#with...
import java.time.LocalDateTime;
import java.time.LocalTime;
public class Main {
public static void main(String[] args) {
String strTime = "15:58:00";
LocalTime time = LocalTime.parse(strTime);
// Today at the specified time
LocalDateTime today = LocalDateTime.now().with(time);
System.out.println(today);
// Today with the updated minute and second
LocalDateTime updated = today.withMinute(1).withSecond(30);
System.out.println(updated);
}
}
Output:
2021-02-23T15:58
2021-02-23T15:01:30
Learn more about the modern date-time API from **[Trail: Date Time](https://docs.oracle.com/javase/tutorial/datetime/index.html)**.
Note: The java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.
For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7.
If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
If I got you right, this should solve your problem
public String nextMeet(int minutes, int seconds) {
LocalDateTime currentDate = LocalDateTime.now();
if ((currentDate.getMinute()*60) + currentDate.getSecond() > (minutes*60) + seconds) {
return (currentDate.getHour() + 1) + ":" + minutes + ":" + seconds;
} else {
return currentDate.getHour() + ":" + minutes + ":" + seconds;
}
}
I've found another solution myself. This library can parse a cron expression and return the next time when it will run, which solves most of my issues. (taken from this question)
Thanks to #OleV.V. for the idea.
Related
This question already has answers here:
Time Difference of two different timezone
(5 answers)
Closed 1 year ago.
I want to calculate the time difference between two different timezones like country1 (GMT+05:30) and country2 (GMT+05:00). How to calculate it. Thanks in advance.
You can find it using java.time.Duration which is modelled on ISO-8601 standards and was introduced with Java-8 as part of JSR-310 implementation. With Java-9 some more convenience methods were introduced.
import java.time.Duration;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
public class Main {
public static void main(String[] args) {
// Test
System.out.println(formatDuration(diffBetweenTimeZones("GMT+05:30", "GMT+05:00")));
System.out.println(formatDuration(diffBetweenTimeZones("GMT+05:00", "GMT+05:30")));
// You can use the returned value to get the ZoneOffset which you can use for
// various kinds of processing e.g.
ZoneOffset offset = ZoneOffset.of(formatDuration(diffBetweenTimeZones("GMT+05:30", "GMT+05:00")));
System.out.println(offset);
System.out.println(OffsetDateTime.now(offset));
}
static Duration diffBetweenTimeZones(String tz1, String tz2) {
LocalDate today = LocalDate.now();
return Duration.between(today.atStartOfDay(ZoneId.of(tz1)), today.atStartOfDay(ZoneId.of(tz2)));
}
static String formatDuration(Duration duration) {
long hours = duration.toHours();
long minutes = duration.toMinutes() % 60;
String symbol = hours < 0 || minutes < 0 ? "-" : "+";
return String.format(symbol + "%02d:%02d", Math.abs(hours), Math.abs(minutes));
// ####################################Java-9####################################
// return String.format(symbol + "%02d:%02d", Math.abs(duration.toHoursPart()),
// Math.abs(duration.toMinutesPart()));
// ####################################Java-9####################################
}
}
Output:
+00:30
-00:30
+00:30
2021-03-24T10:37:31.056405+00:30
Learn more about the modern date-time API from Trail: Date Time.
Note that the java.util date-time API is outdated and error-prone. It is recommended to stop using it completely and switch to the modern date-time API*.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
We want to add days to the current date and format it in a specific way. This was solved in Groovy 2.4.13 and the following date manipulation works fine:
today = new Date()+90;today.format('yyyy-MM-dd HH:mm:ss.S');
Result: 2019-12-02 08:07:15.294
In Groovy 2.5.4 the same expression throws this exception:
groovy.lang.MissingMethodException: No signature of method:
java.util.Date.plus() is applicable for argument types: (Integer)
values: [90] Possible solutions: parse(java.lang.String),
split(groovy.lang.Closure), use([Ljava.lang.Object;),
is(java.lang.Object), wait(), clone() at
Script1.run(Script1.groovy:3)
I was able to reproduce this behaviour in "Groovy sandboxes" online:
Working fine here: groovy-playground (Version 2.4.1.5)
Failing here: groovyconsole (Version 2.5.7)
What is the working alternative in this case? I have read about a new Date API, but couldn't find the details about how to use it, with date manipulation (+ 90 days for example).
Take a look at TimeCategory
import groovy.time.TimeCategory
def theDate = use(TimeCategory){new Date() + 90.days}.format('yyyy-MM-dd HH:mm:ss.S')
I agree with Ole V.V.'s recommendations to use the new Date/Time API. Here is how you would write his Java sample in a more Groovy style.
// you can assemble aggregate types by left shifting the aggregates
// I'm not endorsing this approach, necessarily, just pointing it out as an alternative
ZonedDateTime now = LocalDate.now() << LocalTime.now() << ZoneId.of('Africa/Bamako')
// the plus operator is overloaded
ZonedDateTime in90Days = now + 90
// you can pass a String to format without needed a full DateTimeFormatter instance
println in90Days.format('uuuu-MM-dd HH:mm:ss.S')
While Groovy adds some further support for the old Java Date class, I still believe that you should not use it. It was always poorly designed and is now long outdated. Instead use java.time, the modern Java date and time API. I am sorry that I will have to trust you to translate from Java code.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.S");
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Africa/Bamako"));
ZonedDateTime in90Days = now.plusDays(90);
System.out.println(in90Days.format(formatter));
Output when running just now was:
2020-01-01 08:37:13.3
Please substitute your desired time zone if it didn’t happen to be Africa/Bamako.
Link: Oracle tutorial: Date Time explaining how to use java.time.
You can use Calendar to achieve that
Calendar cal = new GregorianCalendar();
cal.add(Calendar.DATE, 90);
Date date = cal.getTime();
All steps must be separate and not in a single line.
So I got this Instant date in Java: "2018-05-19T22:00:00Z".
How can I get the day of the week? like monday..
I was trying this but it doesn't work:
${date?string["EEEE"]}
Thanks
Freemarker does not work with Instant, so you would need to convert that to string in Java (something like "2018-05-19T22:00:00Z") and then convert the string doing the following:
<#setting locale="en_US">
${"2018-05-19T22:00:00Z"?datetime.iso?string["EEEE"]}
First convert the string to datetime in iso format, and then back again to string with the pattern of your choosing.
By changing the locale setting, you may get the day of the week in different languages.
I think that the best way to work in Freemarker is to always have strings or integers variables.
At this point FreeMarker does not support Java 8 time, see the contribute page:
What should I contribute?
Usually, contributors come because they want to fix/improve a certain thing. But if you just want to help in general, here are some topics ...
Support for Java 8 date/time API-s (this is actually certainly a difficult one). Note that there's a 3rd party solution for this, https://github.com/amedia/freemarker-java-8, but it's not as seamless as a native solution could be.
...
So you could check out the third party solution.
See also:
Java.time (Java 8) support in Freemarker
${date?string["EEEE"]} works fine as long as date is a java.util.Date object.
You can test it in this way:
<#assign date = .now>
${date?string["EEEE"]}
I guess that it doesn't work because your date is a String, in this case you should parse it in Java (server-side) and expose a java.util.Date variable to the template.
I would advise you to use new Date Time API defined in Java 8.Using Date Time API you can fetch all data related to Date and Time easily.
Java 8 has defined a separate Enum for handling days of the week named – DayOfWeek (java.time.DayOfWeek)
java.time.DayOfWeek is an Enum which defines 7 constants representing the seven days of the week – MONDAY(int value=1), TUESDAY(2), WEDNESDAY(3)… till SUNDAY(7).
import java.time.*;
public class Java8Tester {
public static void main(String args[]) {
Java8Tester java8tester = new Java8Tester();
java8tester.testLocalDateTime();
}
public void testLocalDateTime() {
// Get the current date and time
LocalDateTime currentTime = LocalDateTime.parse("2018-05-19T22:00:00");
System.out.println("Current DateTime: " + currentTime);
DayOfWeek dayOfWeek = currentTime.getDayOfWeek();
System.out.println(currentTime + " was a " + dayOfWeek);
}
}
My client/browser is in India and I get the timezoneoffset from javascript
using the following code:
var now = new Date();
var localOffSet = now.getTimezoneOffset(); -330 // for India
int localOffSetMin = (localOffSet)*(-1);
My server is located in New York so I get the offset for it using:
TimeZone timeZone = now.getTimeZone();
int serverOffset = timeZone.getRawOffset();
int serverOffSetMinutes = serverOffset / 60000; // -300 for America/New York
In order to find the local time on my machine, I use this:
int offSets = Math.abs(serverOffSetMinutes-localOffSetMin);
now.setTime(createDt); // createDt is date field value for some column
now.add(Calendar.MINUTE, offSets); // adds offset
Date localDt = now.getTime();
But the date/time I get is 1 hour ahead of the expected time. What am I missing?
Date and Time manipulation with Java SE
You can print a list of supported TimeZones by using the following code.
System.out.println(TimeZone.getAvailableIDs().toString());
You can then find and print the difference between the timezones with the following code. You must be mindful of daylight savings time.
public void printTimeZoneDifference(String from, String to) {
TimeZone easternStandardTime = TimeZone.getTimeZone(from);
TimeZone indiaStandardTime = TimeZone.getTimeZone(to);
long milliseconds = easternStandardTime.getRawOffset() - indiaStandardTime.getRawOffset() + easternStandardTime.getDSTSavings() - indiaStandardTime.getDSTSavings();
String difference = String.format("%02d min, %02d sec", TimeUnit.MILLISECONDS.toMinutes(milliseconds), TimeUnit.MILLISECONDS.toSeconds(milliseconds) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milliseconds)));
System.out.println("The difference in time between" + easternStandardTime.getDisplayName() + " and " + indiaStandardTime.getDisplayName() + " is " + difference);
}
Although if I were to write something like this I would probably pass a TimeZone object as a parameter and keep the method solely responsible for substraction. Then I would either print the results or make it part of a different method. I didn't structure the post that way because I wanted to include all relevant code in the post.
Date and Time manipulation with Joda
This type of manipulation has already been solved in Java. The Joda Time Library is probably your best bet if you are doing a lot of date manipulation. If you are only manipulating time in this one instance then it would be a bit over kill to include the dependency in your runtime.
Again print out the TimeZones.
public void printDateTimeZones() {
for(String zone : DateTimeZone.getAvailableIDs()) {
System.out.println(zone);
}
}
Then you can return a String of the period (difference) between the two DateTimeZones using the default formatting with the following code.
public String printPeriod(String from, String to) {
Period period = new Period(new DateTime(DateTimeZone.forID(to)), new DateTime(DateTimeZone.forID(from)));
return PeriodFormat.getDefault().print(period);
}
Similarly Joda provides a format builder class which allows you to specify your preferred formatting.
public String printPeriod(String from, String to) {
PeriodFormatter formatter = new PeriodFormatterBuilder()
.printZeroRarelyFirst()
.appendYears().appendSuffix(" Years").appendSeparator(",")
.appendMonths().appendSuffix(" Months").appendSeparator(",")
.appendWeeks().appendSuffix(" Weeks").appendSeparator(",")
.appendDays().appendSuffix(" Days").appendSeparator(",")
.appendHours().appendSuffix(" Hours").appendSeparator(",")
.appendSeconds().appendSuffix(" Seconds").appendSeparator(",")
.appendMillis().appendSuffix(" Milliseconds")
.toFormatter();
return formatter.print(new Period(new DateTime(DateTimeZone.forID(from)), new DateTime(DateTimeZone.forID(to))));
}
A java.util.Date object has no timezone information. It has only a long value, which is the number of milliseconds from 1970-01-01T00:00:00Z (also known as "unix epoch" or just "epoch"). This value is absolutely independent of timezone (you can say "it's in UTC" as well).
To convert this value to another timezone, you don't need to do all these math between the timezones. You just get this millis value and convert it to the desired timezone.
To get the value from javascript, just do:
var d = new Date();
var millis = d.getTime();
The variable millis will contain the number of milliseconds from epoch. In the test I've made, this value is 1499101493296.
To create a java.util.Date object, just do:
Date date = new Date(1499101493296L);
To format this date in the timezone you want, use a SimpleDateFormat:
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
System.out.println(sdf.format(date));
The output will be:
03/07/2017 22:34:53
If you want a different format, check the javadoc for more information.
Also note that I used a timezone name using IANA format (always in the format Continent/City, like America/Sao_Paulo or Europe/Berlin).
Avoid using the 3-letter abbreviations (like IST or EST) because they are ambiguous and not standard.
To use another timezone, you can use one the IANA's names - check all the available names using TimeZone.getAvailableIDs().
New Java Date/Time API
The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).
Although you can also use Joda-Time, it is in maintainance mode and is being replaced by the new APIs, so I don't recommend start a new project with it. Even in joda's website it says: "Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".
The code below works for both.
The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.
Once you have the millis value, the code for creating a date and converting to some timezone is very similar:
ZoneId zone = ZoneId.of("Asia/Kolkata");
ZonedDateTime z = Instant.ofEpochMilli(1499101493296L).atZone(zone);
System.out.println(z); // 2017-07-03T22:34:53.296+05:30[Asia/Kolkata]
The output will be:
2017-07-03T22:34:53.296+05:30[Asia/Kolkata]
If you want a different format, use a DateTimeFormatter:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss x");
System.out.println(z.format(fmt)); // 03/07/2017 22:34:53 +0530
The output will be:
03/07/2017 22:34:53 +0530
If you want a different format, check the javadoc for more details.
To use another timezone, you can use one the IANA's names - check all the available names using ZoneId.getAvailableZoneIds().
I want to get the current timestamp like that : 1320917972
int time = (int) (System.currentTimeMillis());
Timestamp tsTemp = new Timestamp(time);
String ts = tsTemp.toString();
The solution is :
Long tsLong = System.currentTimeMillis()/1000;
String ts = tsLong.toString();
From developers blog:
System.currentTimeMillis() is the standard "wall" clock (time and date) expressing milliseconds since the epoch. The wall clock can be set by the user or the phone network (see setCurrentTimeMillis(long)), so the time may jump backwards or forwards unpredictably. This clock should only be used when correspondence with real-world dates and times is important, such as in a calendar or alarm clock application. Interval or elapsed time measurements should use a different clock. If you are using System.currentTimeMillis(), consider listening to the ACTION_TIME_TICK, ACTION_TIME_CHANGED and ACTION_TIMEZONE_CHANGED Intent broadcasts to find out when the time changes.
1320917972 is Unix timestamp using number of seconds since 00:00:00 UTC on January 1, 1970. You can use TimeUnit class for unit conversion - from System.currentTimeMillis() to seconds.
String timeStamp = String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()));
You can use the SimpleDateFormat class:
SimpleDateFormat s = new SimpleDateFormat("ddMMyyyyhhmmss");
String format = s.format(new Date());
Use below method to get current time stamp. It works fine for me.
/**
*
* #return yyyy-MM-dd HH:mm:ss formate date as string
*/
public static String getCurrentTimeStamp(){
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String currentDateTime = dateFormat.format(new Date()); // Find todays date
return currentDateTime;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
It's simple use:
long millis = new Date().getTime();
if you want it in particular format then you need Formatter like below
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String millisInString = dateFormat.format(new Date());
You can get Current timestamp in Android by trying below code
time.setText(String.valueOf(System.currentTimeMillis()));
and timeStamp to time format
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
String dateString = formatter.format(new Date(Long.parseLong(time.getText().toString())));
time.setText(dateString);
Here's a human-readable time stamp that may be used in a file name,
just in case someone needs the same thing that I needed:
package com.example.xyz;
import android.text.format.Time;
/**
* Clock utility.
*/
public class Clock {
/**
* Get current time in human-readable form.
* #return current time as a string.
*/
public static String getNow() {
Time now = new Time();
now.setToNow();
String sTime = now.format("%Y_%m_%d %T");
return sTime;
}
/**
* Get current time in human-readable form without spaces and special characters.
* The returned value may be used to compose a file name.
* #return current time as a string.
*/
public static String getTimeStamp() {
Time now = new Time();
now.setToNow();
String sTime = now.format("%Y_%m_%d_%H_%M_%S");
return sTime;
}
}
Here is the comparison list of the most widely known methods
Solution in Kotlin:
val nowInEpoch = Instant.now().epochSecond
Make sure your minimum SDK version is 26.
java.time
I should like to contribute the modern answer.
String ts = String.valueOf(Instant.now().getEpochSecond());
System.out.println(ts);
Output when running just now:
1543320466
While division by 1000 won’t come as a surprise to many, doing your own time conversions can get hard to read pretty fast, so it’s a bad habit to get into when you can avoid it.
The Instant class that I am using is part of java.time, the modern Java date and time API. It’s built-in on new Android versions, API level 26 and up. If you are programming for older Android, you may get the backport, see below. If you don’t want to do that, understandably, I’d still use a built-in conversion:
String ts = String.valueOf(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()));
System.out.println(ts);
This is the same as the answer by sealskej. Output is the same as before.
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Here is another solution, this is in kotlin:
val df: DateFormat = SimpleDateFormat("yyyy.MM.dd HH:mm:ss")
val timeStamp = df.format(Calendar.getInstance().time)
Output example:
"2022.04.22 10:22:35"
I suggest using Hits's answer, but adding a Locale format, this is how Android
Developers recommends:
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
return dateFormat.format(new Date()); // Find todays date
} catch (Exception e) {
e.printStackTrace();
return null;
}
This code is Kotlin version. I have another idea to add a random shuffle integer in last digit for giving variance epoch time.
Kotlin version
val randomVariance = (0..100).shuffled().first()
val currentEpoch = (System.currentTimeMilis()/1000) + randomVariance
val deltaEpoch = oldEpoch - currentEpoch
I think it will be better using this kode then depend on android version 26 or more