Writing a Java application that takes user input into a Time and Date class, but I am not sure how to take this user input and convert it into Universal and Standard time... I have spent multiple hours surfing the web and stack overflow and have not been able to find a solution.
I have hours, minutes, seconds, year, month, day all in separate integer variables and need to display them in Universal and Standard time.
Thanks for taking a look...
There are two solutions:
first is place all of input in the string and parse it:
String dateStr = ""
//put your input in this string in some format/ example:
//dateSttr = year + "." + month + "." + day + " " + hour + ":" + minute;
//It is better to use StringBuilder
DateFormat inputFormat = new SimpleDateFormat("yyyy.MM.dd hh:mm");
//note that hh is 12h-format and HH is 24h-format
DateFormat outputFormat1 = new SimpleDateFormat("your_outputFormat");
DateFormat outputFormat2 = new SimpleDateFormat("your_another_outputFormat");
Date date = inputFormat.parse(dateStr);
String o1, o2;
o1 = outputFormat1.format(date);
o2 = outputFormat2.format(date);
//o1 and o2 is your result.
For the rules, how this formats is done, see javadoc
The second solution is to get a new date and set your parameters:
Calendar cln = Calendar.getInstance().clear();
//by default you get a calendar with current system time
//now set the fields. for example, day:
cln.set(Calendar.YEAR, 2015);
cln.set(Calendar.MONTH, Calendar.FEBRUARY);
cln.set(Calendar.DAY_OF_MONTH, 17);
cln.set(Calendar.HOUR_OF_DAY, 18);//Calendar.HOUR for 12h-format
cln.set(Calendar.MINUTE, 27);
See more about setting calendar in javadoc
Note, that in the second variant, you might have some fields undefiend.
If #JonSkeet 's assumption and mine is correct, you're starting with either UTC or your local time. Displaying it is just a matter of formatting your output.
For the other type of time, you add or subtract a number of hours, which you can find on the web. The tricky part is that this may push you into the next calendar day, or pull you back into the previous one. To deal with that, I figure you want to either
implement an adder for year, month, day, hour--or
convert those to decimal somethings (Excel uses days, for instance, where as I write this it's 42328.08813), shift the value by the appropriate number of hours, and convert it back.
java.time
The Answer by TEXHIK is correct, but outdated. Also, as others mentioned, I do not know what you mean by "Universal and Standard time". But I'll try to get you part way there.
As of Java 8, the old java.util.Date/.Calendar classes have been supplanted by the new java.time framework. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
The ZonedDateTime class has a factory method taking numbers for year, month, and so on.
Plus you must specify a time zone. If your numbers represent a date-time in UTC, use the ZoneOffset.UTC constant. For other time zones, specify a ZoneId object by using a proper time zone name; never use the 3-4 letter codes such as EST or IST as their are neither standardized nor unique.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
// ZoneId zoneId = ZoneOffset.UTC; // ZoneOffset is a subclass of ZoneId.
ZonedDateTime zdt = ZonedDateTime.of( 2015 , 1 , 2 , 3 , 4 , 5 , 6 , zoneId );
zdt: 2015-01-02T03:04:05.000000006-05:00[America/Montreal]
You can convert to UTC or another time zone.
ZonedDateTime zdt_Kolkata = zdt.withZoneSameInstant ( ZoneId.of("Asia/Kolkata") );
ZonedDateTime zdt_Utc = zdt.withZoneSameInstant ( ZoneOffset.UTC );
zdt_Kolkata: 2015-01-02T13:34:05.000000006+05:30[Asia/Kolkata]
zdt_Utc: 2015-01-02T08:04:05.000000006Z
If working with classes not yet updated for java.time, convert to a java.util.Date. First extract a Instant object, a moment on the timeline always in UTC.
java.util.Date date = java.util.Date.from ( zdt.toInstant () );
Related
I am trying to get the start time (00:00:00) and the end time (23:59:59) of a day in the PST time zone. I have tried the following code, but for some reason, I am only getting the start and end times in UTC. I have tried changing the timezone to include "America/Los_angeles", but the output timestamp is always showing start and end times for GMT/UTC.
My code:
val time_zone = ZoneId.of("America/Los_Angeles")
val today_date = LocalDate.now(time_zone).plusDays(0)
val start_time = today_date + " " + "00:00:00"
val end_time = today_date + " " + "23:59:59"
val date_format = new SimpleDateFormat("yyyy-MM-dd");
val start_millis = date_format.parse(start_time).getTime();
val end_millis = date_format.parse(end_time).getTime();
start_millis
Output:
res375: Long = 1656460799000
In the epoch converter, 1656460799000 gives me this:
Anything I am missing here? Should I update any package, etc.?
java.time
The modern approach uses the java.time classes only.
No need to ever use SimpleDateFormat, Date, Calendar, and the other terrible legacy date-time classes. If need be, you can convert to and fro via new conversion methods added to the old classes.
Start of day
I am trying to get the start time (00:00:00)
Do not assume the day starts at 00:00. Some dates in some zones start at another time such as 01:00. Let java.time determine the first moment of the day using LocalDate#atStartOfDay.
End of day
the end time (23:59:59) of a day
You would be missing an entire last second of the day with that approach.
Date-time work is commonly done with the Half-Open approach. In Half-Open, the beginning is inclusive while the ending is exclusive. So a day starts with the first moment of the day, and runs up to, but does not include, the first moment of the following day. Half-Open approach neatly contains that full last second of the day.
Time zones
PST time zone.
There is no such thing as a time zone named PST. Such 2-4 letter pseudo-zones are used by the popular media to indicate a hint about the time zone. But these pseudo-zones are not standardized, and are not even unique! Use only for localized presentation to humans, never for data storage or data exchange.
Real time zones are named with Continent/Region.
Perhaps by “PST” you meant “Pacific Standard Time”, which often indicates America/Tijuana, or America/Los_Angeles or America/Vancouver or others.
Or perhaps by “PST” you meant “Philippines Standard Time” covering the Asia/Manila time zone.
Example code
Capture the current moment as seen in a time zone.
ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
Extract the date.
LocalDate today = zdt.toLocalDate() ;
Determine the first moment of the day.
ZonedDateTime zdtStartOfDay = today.atStartOfDay( z ) ;
And determine the first moment of the following day.
ZonedDateTime zdtStartOfFollowingDay = today.plusDays( 1 ).atStartOfDay( z ) ;
You may want to see the length of time. Not all days are 24 hours.
Duration d = Duration.between( zdtStartOfDay , zdtStartOfFollowingDay ) ;
Adjust both moments to UTC by extracting an Instant object. That class represents a moment as seen in UTC.
Instant start = zdtStartOfDay.toInstant() ;
Instant end = zdtStartOfFollowingDay.toInstant() ;
For each, get the count of milliseconds since the epoch reference of first moment of 1970 as seen in UTC, 1970-01-01T00:00Z.
long startMilli = start.toEpochMilli() ;
long endMilli = end.toEpochMilli() ;
However, I strongly recommend against tracking time as a count of milliseconds. This approach is confusing, as at least a couple dozen epoch reference points are commonly used. And a long cannot be interpreted by a human reader, so mistakes may go unnoticed.
Instead, data storage and data exchange should generally be done as text using the standard ISO 8601 formats. The java.time classes use these standard formats by default when parsing/generating text.
String startText = start.toString() ;
String endText = end.toString() ;
ThreeTen-Extra
You may want to add the ThreeTen-Extra library to your project. This gives you access to the Interval class, to represent a span of time as a pair of Instant objects.
Interval allDayLongToday = org.threeten.extra.Interval.of( start , end ) ;
This class provides several helpful methods. These include contains, encloses, abuts, union, intersection, and more.
Instant invoiceRecorded = … some `Instant` ;
boolean invoiceRecordedToday = allDayLongToday.contains( invoiceRecorded ) ;
Just add this section to your code:
date_format.setTimeZone(TimeZone.getTimeZone("PST"));
Then it will work as you want :)
How to format java.util.Date with DateTimeFormatter portable?
I can't use
Date in = readMyDateFrom3rdPartySource();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
ldt.format(dateTimeFormatter);
because I afraid that usage of ZoneId.systemDefault() can introduce some changes.
I need to format exactly that object I have.
UPDATE
Note: time is time. Not space. Timezone is very rough measure of longitude, i.e. space. I don't need it. Only time (and date).
UPDATE 2
I wrote the following program, proving, that Date DOES NOT only contain correct "instant":
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DataNature2 {
public static void main(String[] args) throws ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateTimeString = "1970-01-01 00:00:01";
Date date = simpleDateFormat.parse(dateTimeString);
System.out.println("1 second = " + date.getTime());
}
}
The output is follows:
1 second = -10799000
While it should be
1 second = 1000
if Date was "Instant".
The number 10799000 is 3*60*60*1000-1000 - the timezone offset of my local time.
This means, that Date class is dual. It's millisecond part may be shifted relatively to hh mm ss part by timezone offset.
This means, that if any utility returns Date object in terms of it's parts (hh mm ss) then it implicitly converted to local time. And getTime() means DIFFERENT time simultaneously. I mean on different machines if this program run at the same time, getTime() will be the same, while time parts will be different.
So, the code example in the beginning is correct: it takes "instant" part of Date, and supplies system timezone part, which was implicitly used inside Date. I.e. it converts dual Date object into explicit LocalDateTime object with the same parts. And hence, formatting after that, is correct.
UPDATE 3
Event funnier:
Date date = new Date(70, 0, 1, 0, 0, 1);
assertEquals(1000, date.getTime());
this test fails.
UDPATE 4
New code. Dedicated to all believers.
public class DataNature3 {
public static class TZ extends java.util.TimeZone {
private int offsetMillis;
public TZ(int offsetHours) {
this.offsetMillis = offsetHours * 60 * 60 * 1000;
}
#Override
public int getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds) {
throw new UnsupportedOperationException();
}
#Override
public void setRawOffset(int offsetMillis) {
this.offsetMillis = offsetMillis;
}
#Override
public int getRawOffset() {
return offsetMillis;
}
#Override
public boolean useDaylightTime() {
return false;
}
#Override
public boolean inDaylightTime(Date date) {
return false;
}
}
public static void main(String[] args) {
Date date = new Date(0);
for(int i=0; i<10; ++i) {
TimeZone.setDefault(new TZ(i));
if( i<5 ) {
System.out.println("I am date, I am an instant, I am immutable, my hours property is " + date.getHours() + ", Amen!");
}
else {
System.out.println("WTF!? My hours property is now " + date.getHours() + " and changing! But I AM AN INSTANT! I AM IMMUTABLE!");
}
}
System.out.println("Oh, please, don't do that, this is deprecated!");
}
}
Output:
I am date, I am an instant, I am immutable, my hours property is 0, Amen!
I am date, I am an instant, I am immutable, my hours property is 1, Amen!
I am date, I am an instant, I am immutable, my hours property is 2, Amen!
I am date, I am an instant, I am immutable, my hours property is 3, Amen!
I am date, I am an instant, I am immutable, my hours property is 4, Amen!
WTF!? My hours property is now 5 and changing! But I AM AN INSTANT! I AM IMMUTABLE!
WTF!? My hours property is now 6 and changing! But I AM AN INSTANT! I AM IMMUTABLE!
WTF!? My hours property is now 7 and changing! But I AM AN INSTANT! I AM IMMUTABLE!
WTF!? My hours property is now 8 and changing! But I AM AN INSTANT! I AM IMMUTABLE!
WTF!? My hours property is now 9 and changing! But I AM AN INSTANT! I AM IMMUTABLE!
Oh, please, don't do that, this is deprecated!
TL;DR: You're right to be concerned about the use of the system local time zone, but you should have been concerned earlier in the process, when you used the system local time zone to construct a Date in the first place.
If you just want the formatted string to have the same components that Date.getDate(), Date.getMonth(), Date.getYear() etc return then your original code is appropriate:
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
You say you're "afraid that usage of ZoneId.systemDefault() can introduce some changes" - but that's precisely what Date.getDate() etc use.
Date doesn't have any kind of "dual contract" that lets you view it as a time-zone-less representation. It is just an instant in time. Almost every single method that lets you construct or deconstruct it into components is clearly documented to use the system default time zone, just like your use of ZoneId.systemDefault(). (One notable exception is the UTC method.)
Implicitly using the system default time zone is not the same as Date being a valid time-zone-less representation, and it's easy to demonstrate why: it can lose data, very easily. Consider the time-zone-free date and time of "March 26th 2017, 1:30am". You may well want to be able to take a text representation of that, parse it, and then later reformat it. If you do that in the Europe/London time zone, you'll have problems, as demonstrated below:
import java.util.*;
import java.time.*;
import java.time.format.*;
public class Test {
public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
Date date = new Date(2017 - 1900, 3 - 1, 26, 1, 30);
Instant instant = date.toInstant();
ZoneId zone = ZoneId.systemDefault();
LocalDateTime ldt = LocalDateTime.ofInstant(instant, zone);
System.out.println(ldt); // Use ISO-8601 by default
}
}
The output is 2017-03-26T02:30. It's not that there's an off-by-one error in the code - if you change it to display 9:30am, that will work just fine.
The problem is that 2017-03-26T01:30 didn't exist in the Europe/London time zone due to DST - at 1am, the clock skipped forward to 2am.
So if you're happy with that sort of brokenness, then sure, use Date and the system local time zone. Otherwise, don't try to use Date for this purpose.
If you absolutely have to use Date in this broken way, using methods that have been deprecated for about 20 years because they're misleading, but you're able to change the system time zone, then change it to something that doesn't have - and never has had - DST. UTC is the obvious choice here. At that point, you can convert between a local date/time and Date without losing data. It's still a bad use of Date, which is just an instant in time like Instant, but at least you won't lose data.
Or you could make sure that whenever you construct a Date from a local date/time, you use UTC to do the conversion, of course, instead of the system local time zone... whether that's via the Date.UTC method, or by parsing text using a SimpleDateFormat that's in UTC, or whatever it is. Unfortunately you haven't told us anything about where your Date value is coming from to start with...
tl;dr
How to format java.util.Date with DateTimeFormatter portable?
Instant instant = myJavaUtilDate.toInstant() ; // When encountering a `Date`, immediately convert from troublesome legacy class to modern *java.time* class. Then forget all about that `Date` object!
ZoneId z = ZoneId.systemDefault() ; // Or ZoneId.of( "America/Montreal" ) or ZoneId.of( "Africa/Tunis" ) etc.
ZonedDateTime zdt = instant.atZone( z ) ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ;
String output = zdt.format( f ) ;
Or, a one-liner… (not that I recommend such a complicated one-liner)
myJavaUtilDate.toInstant().atZone( ZoneId.systemDefault() ).format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) )
Details
The Answer by Jon Skeet is correct. Here is my own take, with some specific points.
Avoid legacy date-time classes.
Do not use java.util.Date, java.util.Calendar, SimpleDateFormat, java.sql.Date/Time/Timestamp and other related classes dating back to the earliest versions of Java. While a well-intentioned early attempt at sophisticated handling of date-time values, they fell short of the mark. Now supplanted by the java.time classes.
If you must inter-operate with the legacy classes in old code not yet updated for java.time, convert. Call new methods on the old classes.
Instant instant = myJavaUtilDate.toInstant() ;
You did this in your Question, but then went on to ponder more about Date. Forget about java.util.Date. Pretend it never existed. Both Date and Instant represent the same thing: A moment in UTC, a point on the timeline. The only difference is concept is that the modern Instant has a finer resolution of nanoseconds rather than milliseconds in Date.
LocalDateTime != moment
You then converted from an Instant to a LocalDateTime. You moved from a specific point on the timeline, to a vague range of possible moments. This makes no sense in nearly any practical scenario.
A LocalDateTime lacks any concept of time zone or offset-from-UTC. Having no such concept is its very purpose. Ditto for LocalDate & LocalTime: no concept of zone/offset. Think of the “Local” part as meaning “any locality” or “no locality”, not any one particular locality.
Lacking zone/offset means a LocalDateTime does not represent a moment. It is not a point on the timeline. It is a vague idea about potential moments, along a range of about 26-27 hours. Until you place a LocalDateTime in a context of a particular zone or offset, it has no real meaning.
Use LocalDateTime for use such as “Christmas this year starts at first moment of December 25th, 2018”. Such a statement implies anywhere, or nowhere specifically.
LocalDate ld = LocalDate.of(2018, Month.DECEMBER , 25);
LocalTime lt = LocalTime.MIN ; // 00:00
LocalDateTime xmasStartsAnywhere = LocalDateTime.of( ld , lt ) ;
xmasStartsAnywhere.toString(): 2018-12-25T00:00
ZonedDateTime = moment
Now add in the context of a time zone. The first kids getting their delivery from Santa will be asleep in their beds on Kiritimati (“Christmas Island”) in the first hour of the 25th as seen on the wall-clocks of their homes.
ZoneId z = ZoneId.of("Pacific/Kiritimati");
LocalDate ld = LocalDate.of(2018, Month.DECEMBER , 25);
ZonedDateTime zdtKiritimati = ZonedDateTime.of( ld , LocalTime.MIN , z );
zdtKiritimati.toString(): 2018-12-25T00:00+14:00[Pacific/Kiritimati]
By the way, we could have assigned that time zone (ZoneId) directly to to our LocalDateTime to get a ZonedDateTime rather than start from scratch.
ZonedDateTime zdtKiritimati = xmasStartsAnywhere.atZone( z ) ; // Move from the vague idea of the beginning of Christmas to the specific moment Christmas starts for actual people in an actual location.
Meanwhile, at the very same moment Santa is laying out presents in Kiribati, the kids on the farms in Québec are just rising at 5 AM the day before (Christmas Eve) to milk the cows and tap the maple sap.
ZonedDateTime zdtMontreal = zdtKiribati.withZoneSameInstant( ZoneId.of( "America/Montreal") );
zdtMontreal.toString(): 2018-12-24T05:00-05:00[America/Montreal]
So, after finishing in Kiribati, the elves route Santa westward, moving through a succession of new midnight hours, starting in the far east Asia & New Zealand, then India, then the Middle East, then Africa & Europe, and eventually the Americas. The offsets currently range from 14 hours ahead of UTC to 12 hours behind. So Santa has just over 26 hours to get the job done.
Epoch
Regarding your experiments with the epoch reference of first moment of 1970 in UTC, you were inadvertently injecting your own JVM’s current default time zone. Your input string 1970-01-01 00:00:01 is faulty in that it lacks any indicator of a time zone or offset-from-UTC. In other words, that input string is the equivalent of a LocalDateTime object. When parsing that string as a Date (having UTC), the Date class silently implicitly applied your JVM’s current default time zone while interpreting that input string, in a desperate attempt to create meaning, to determine a specific moment. Once again you are inappropriately mixing a date-time lacking any concept of zone/offset with a date-time having a zone/offset.
Per the documentation for Date.parse:
If a time zone or time-zone offset has been recognized, then the year, month, day of month, hour, minute, and second are interpreted in UTC and then the time-zone offset is applied. Otherwise, the year, month, day of month, hour, minute, and second are interpreted in the local time zone.
That “local” in the last sentence was a poor choice of words. Should have been written “interpreted by applying your JVM’s current default time zone”.
The key here is that you failed to specify a zone/offset, and the Date class filled in the missing information. A well-intentioned feature, but confusing and counter-productive.
Moral of the story: If you intend a specific moment (a point on the timeline), always specify your desired/intended time zone explicitly.
If you mean UTC, say UTC. In this next line, we include a Z on the end, short for Zulu and means UTC. This part about specifying UTC is where you went wrong by omission.
Instant instant = Instant.parse( "1970-01-01T00:00:01Z" ) ; // One second after the first moment of 1970 **in UTC**.
instant.toString(): 1970-01-01T00:00:01Z
By the way, another way of writing that code is to use a constant defined for the epoch reference 1970-01-01T00:00:00Z, and the Duration class for representing a span of time unattached to the timeline.
Instant instant = Instant.EPOCH.plus( Duration.ofSeconds( 1 ) ) ;
instant.toString(): 1970-01-01T00:00:01Z
Your next experiment has the same story. You failed to specify a zone/offset, so Date applied one while interpreting your zone-less input. A bad idea in my opinion, but that is the documented behavior.
Date date = new Date(70, 0, 1, 0, 0, 1);
assertEquals(1000, date.getTime()); // fails
You can see from the Date object’s generated string that it represents a date-time of one second after 1970 starts in another time zone rather than in UTC. Here is output from my JVM with default time zone of America/Los_Angeles.
date.toString(): Thu Jan 01 00:00:01 PST 1970
Let's convert to Instant for clarity. Notice how the hour-of-day is 8 AM in UTC. On that first day of 1970, people in zone America/Los_Angeles used a wall-clock time eight hours behind UTC. So one second after midnight, 00:00:01, on much of the west coast of North America is simultaneously 8 AM in UTC. Nothing “funny” going on here at all.
Instant instant = date.toInstant() ; // 00:00:01 in `America/Los_Angeles` = 8 AM UTC (specifically, 08:00:01 UTC).
instant.toString(): 1970-01-01T08:00:01Z
Two important pieces are in play here:
You must learn and understand that a moment, a point on the timeline, has different wall-clock time used by different different people in different places around the globe. In other words, the wall-clock time for any given moment varies around the globe by time zone.
The poor design choices of the legacy date-time classes such as java.util.Date unfortunately complicate the situation. The ill-advised behavior brings confusion rather than clarity to the already confusing topic of date-time handling. Avoid the legacy classes. Use only java.time classes instead. Stop banging your head against a brick wall, and then your headache will go away.
Tips:
Learn to think, work, debug, log, and exchange data in UTC. Think of UTC as The One True Time™. Avoid translating back-and-forth between your own parochial time zone and UTC. Instead forget about your own zone and focus on UTC while at work programming/administrating. Keep a UTC clock on your desktop.
Apply a time zone only when required by business logic or by expectation of user in presentation.
Always specify your desired/expected time zone explicitly as optional argument. Even if you intend to use the current default value, explicitly call for the default, to make your code self-documenting about your intention. By the way… Ditto for Locale: always specify explicitly, never rely implicitly on default.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
you can use as per your requirment.
java.util.Date
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
System.out.println(dateFormat.format(date));
java.util.Calendar
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar cal = Calendar.getInstance();
System.out.println(dateFormat.format(cal.getTime()));
java.time.LocalDateTime
DateTimeFormatter dateTimeFormat = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(dateTimeFormat.format(localDateTime));
I have stored date in a string. Now I want to get minutes from the date string. How can I convert it into minutes?
Here is how I stored in a class:
public String fromDate;
public String toDate;
I have set getter and setter methods. I have saved the date value now I want to retrive the value and convert to minutes.
Retriving Like this:
Calendar c = Calendar.getInstance();
String datefrom = eventData.getFromDate();
I tried using this calendar instance:
c.set(Calendar.HOUR, hour);
c.set(Calendar.MINUTE, minute);
c.set(Calendar.DATE,day);
Date datefrom = c.getTime();
startTime = String.valueOf(datefrom);
int hour = c.get(Calendar.HOUR);
int totalMinutes = hour * 60;
But this I can get from Date object. I have stored date in String format. How can I convert this?
Use Joda-Time:
String fromDate;
String toDate;
DateTimeFormatter format = new DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
DateTime fromDT = format.parseDateTime(fromDate);
DateTime toDT = format.parseDateTime(toDate);
Duration duration = new Duration(fromDT, toDT);
int minutes = duration.getStandardMinutes();
To import in Android Studio, update your build.gradle file:
apply plugin: 'android'
dependencies {
compile 'joda-time:joda-time:2.4'
compile 'joda-time:joda-time:2.2'
}
To convert a String to Date in Java you would have to use the DateFormat like the sample below:
String string = "January 26, 2016";
DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
Date date = format.parse(string);
System.out.println(date); // Tue Jan 26 00:00:00 GMT 2016
then you can go ahead with your Calendar implementation.
Usually i'd suggest to parse the time with a SimpleDateFormat, but I think in this case (since the dates seem to have a defined form and there might be problems with the timezones) i'll suggest to retrieve the information yourself:
String date = "Wed Jan 27 07:25:29 GMT+05:30 2016";
String[] times = date.substring(11, 16).split(":");
int minutes = Integer.parseInt(times[0]) * 60 + Integer.parseInt(times[1]);
System.out.println(minutes);
The part date.substring(11, 16) extracts the hours and minutes part from the string ("07:25").
The part .split(":"); splits the string "07:25" into two strings: "07" and "25".
after that you just parse those numbers to integers with Integer.parseInt(...) and calculate the number of minutes!
To get the minutes from a String is possible to use a DateFormat to convert the string to a Date and after use your code.
Your Question is really two questions:
How to parse a String to get a date-time object
How to get number of minutes since start-of-day from a date-time object
The first one, parsing a String into a date-time, has been covered at least 1,845 times on Stack Overflow, so I will skip it. The second Question is addressed below.
Please try to make your questions more clear. And focus on a single topic as narrowly as possible, as that is the intention for Stack Overflow.
Minutes-Of-Day
What you seem to want is called “Minutes-Of-Day”, the number of minutes since the start of the day.
Be careful and thoughtful here as there are two different definitions for minutes-of-day. You can get the actual number of minutes for a specific day in a specific time zone. Or you can calculate for a generic 24-hour day. Because of Daylight Saving Time (DST) and other anomalies, a day is not necessarily 24 hours long. For example, in most of the United States the use of DST means a day may be 23, 24, or 25 hours long.
The Question’s code and other Answers ignore the crucial issue of time zone (a common mistake in date-time work). If you do not specify a time zone, your JVM’s current default time zone is silently applied. Not good… that default can change at any moment, even during runtime! Better to always specify the time zone you expect/desire.
Avoid Old Date-Time Classes
The old date-time classes bundled with the earliest versions of Java are notoriously troublesome. Avoid them. Instead use the java.time framework built into Java 8 and later (see Tutorial). If that technology is not available to you, use the Joda-Time library (which inspired java.time). Examples below are in java.time in Java 8 Update 66.
java.time
Let’s look at March 3rd, 2015. This day was the "Spring ahead" DST changeover day for most of the United States. The clock jumped from 2 AM to 3 AM. So 03:00:00.0 on this day meant two hours (120 minutes) actually elapsed since the start of the day. If we treat this as a generic 24-hour day, we would say three hours (180 minutes) elapsed. The java.time classes can calculate minutes-of-day in both definitions.
First we get 3 AM on that changeover day. We use one of the time zones which recognized DST.
ZoneId zoneId = ZoneId.of ( "America/Los_Angeles" );
ZonedDateTime zdt = ZonedDateTime.of ( 2015 , 3 , 8 , 3 , 0 , 0 , 0 , zoneId );
Generic 24-Hour Day
Next we get the minutes since start of day assuming a generic 24-hour day. The ChronoField enum provides many ways to access TemporalField values such as MINUTE_OF_DAY.
long minutesOfDayForGeneric24HourDay = zdt.get ( ChronoField.MINUTE_OF_DAY );
Actual Day
To get the actual number of minutes elapsed since the start of this particular day for this particular time zone in which DST was changing over, we must do a bit more work. We have to determine the first moment of the day from which we can calculate elapsed time. To get that first moment, we must go through the LocalDate class which is a date-only value without time-of-day nor time zone. On that LocalDate object we call atStartOfDay to adjust back into a date-time value (a ZonedDateTime). You might think you could skip this by assuming the day starts at 00:00:00.0 but that is not always true.
ZonedDateTime zdtStart = zdt.toLocalDate ().atStartOfDay ( zoneId );
Now calculate elapsed time. The Duration class represents a span of time as hours, minutes, and seconds. From that Duration we can ask the total number of minutes, converting hours to minutes.
Duration duration = Duration.between ( zdtStart , zdt );
long minutesOfDayForActualDay = duration.toMinutes ();
Dump to console. Note how the generic ChronoField approach says 180 minutes while the actual Duration approach yields 120 minutes.
System.out.println ( "zdt: " + zdt + " | minutesOfDayForGeneric24HourDay: " + minutesOfDayForGeneric24HourDay + " | duration: " + duration + " | minutesOfDayForActualDay: " + minutesOfDayForActualDay );
zdt: 2015-03-08T03:00-07:00[America/Los_Angeles] | minutesOfDayForGeneric24HourDay: 180 | duration: PT2H | minutesOfDayForActualDay: 120
I have a Date field in my class that can has two types of values: with and without time. Something like this: 2015-01-01 and 2015-01-01 12:00:00. I want to make formatted string from my date. I know I can use SimpleDateFormat class for doing this, but I don't know the format. In fact, If my date has the time part, I must use yyyy-MM-dd HH:mm:ss format and if my date does not have the time part, I must use yyyy-MM-dd format. My question is, Is there anyway to check a date has time section before formatting it?
Here is my code:
private SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
.....
private String formatDate(Date date){
//I need to something like this:
if(/* `date` has time part */){
return dateTimeFormat.format(date);
}
else{
return dateFormat.format(date);
}
}
You cannot reliably do that, because once you create a Date object, it is represented as a number in milliseconds, which includes the specific time. For this reason you cannot possibly know how the object was built and if the specific time was set.
A workaround would be to check if the hours, minutes and seconds are set to zero. Keep in mind that there is a small probability that the date was parsed as "yyyy-MM-dd HH:mm:ss", but all these values were set to 0, simply because the time was indeed 00:00:00. However, this probability is equal to 1 / (24 * 60 * 60) = 0.00001157407, so I assume that you can live with that.
A Big Mess
As shown in the other answers, the old date-time classes bundled with Java such as java.util.Date and java.sql.Date are a mess. They were rushed to market, with bad design decisions. Specifically a java.util.Date represents both a date and a time-of-day, while its subclass java.sql.Date pretends not to have a time-of-day but actually does. The doc explains that you are supposed to ignore this inheritance relationship to help maintain the illusion. Not good.
java.time
This whole mess has been supplanted by the java.time framework built into Java 8 and later. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
Date-Only
Among the new classes is LocalDate. This is the first class bundled with Java for representing a date only, without time-of-day nor time zone. To determine a date such as "today", you need a time zone (a ZoneId). For example, a new day dawns earlier in Paris than in Montréal. When you need a date-only value, I suggest you add a member to your class of this type.
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
Date-Time
If you want a date-time, first consider the Instant class. This marks a moment on the timeline in UTC. Almost always best to do your business logic and data storage in UTC. When you need a specific moment in time rather than a vague date, add a member of this type to your class.
Instant now = Instant.now();
For presentation to the user in their desired/expected time zone, apply a time zone to an Instant to get a ZonedDateTime.
ZonedDateTime zdt = ZonedDateTime.ofInstant( now , ZoneId.of( "America/Montreal" ) );
First Moment Of The Day
I do not recommend this strategy, but to directly answer your Question about detecting if the time-of-day in a date-time value happens to be the first moment of the day…
First you need to think about time zone. All of these date-time classes mentioned above track time by a count-from-epoch in UTC. The old classes count in milliseconds, the new in nanoseconds. The epoch for both old and new is the first moment of 1970 in UTC. So there is no such thing as a date-time without a time, as you pose it in the Question. The closest thing to that is a date-time whose time-of-day happens to be the first moment of the day. Seems to be your situation (though my discussion above strongly recommends you change your situation).
How to determine if a date-time has a time-of-day that is the first moment of the day? First you must consider time zone. Either you want UTC or you want a particular time zone such as America/Montreal. Depends on your business rules.
If starting with a java.util.Date, first convert to java.time.
Instant instant = myJUDate.toInstant();
Be aware that a date does not always start at the time 00:00:00.0. Because of Daylight Saving Time (DST), and possibly other anomalies, in some places the first moment of the date is a different wall-clock time. The java.time framework can determine this first moment of the day by using the LocalDate class and its atStartOfDay methods.
So after determining the time zone we care about, we adjust our Instant into a ZonedTimeZone.
Instant instant = Instant.now ();
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
Next we need to see if that is first moment of the day. So we convert to a LocalDate, then back to another ZonedDateTime by calling atStartOfDay. Comparing the first ZonedDateTime to the second tells us if the original was indeed at the start of the day. To sum it up: We are converting from ZonedDateTime → LocalDate → ZonedDateTime.
// Convert to LocalDate, to get start of day, to compare to above.
LocalDate localDate = zdt.toLocalDate ();
ZonedDateTime startOfDay = localDate.atStartOfDay ( zoneId );
Boolean isStartOfDay = ( zdt.isEqual ( startOfDay ) );
Dump to console.
System.out.println ( "instant: " + instant + " for zoneId: " + zoneId + " is zdt: " + zdt + " if compared to startOfDay: " + startOfDay + " is T/F: " + isStartOfDay );
instant: 2015-12-12T23:20:23.560Z for zoneId: America/Montreal is zdt: 2015-12-12T18:20:23.560-05:00[America/Montreal] if compared to startOfDay: 2015-12-12T00:00-05:00[America/Montreal] is T/F: false
If you want UTC rather than a particular time zone, in the code above use the constant ZoneOffset.UTC as your ZoneId object. ZoneOffset is a subclass of ZoneId.
Assuming you're using java.sql.Date which derives from java.util.Date there is no possibility of a Date object not having a time value.
Note the documentation:
http://docs.oracle.com/javase/7/docs/api/java/sql/Date.html
A Date object instance holds a miliseconds value, to be precise the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC.
Use a Calendar object. The calendar can give you structured access to all fields of a Date value, i.e. year, month, day, hours, minutes, seconds, etc. This would allow you to check whether the time fields are non-zero. As JB Nizet stated, the time part can happen to be zero, in which case wou would misinterpret it as a date only value.
I want to store a user-specified rough time of day (unspecified date) in a Java object. Can I instantiate a LocalTime object and set its hours and minutes in one line of Java code? Or is there a different, more suitable existing class?
I have insufficient google wizardry to find such. Elaboration follows, and thank you:
< 1 year android/java exp.
I'm extending the GregorianCalendar class and coding a constructor for FutureCal that takes integer hour (0-23) and minute and returns a calendar-ish object with date/time matching the first future occurrence of that hour:minute (will be either today or tomorrow--for notification/reminder stuff). To allow for other constructors that might have two integers, I would like to use or create a TimeOfDay class/type (comprised of integers hour & minute) and use that instead as parameter to my constructor. Is this a) possible b) appropriate?
Thanks for your time.
Joda-Time
The Joda-Time library is a popular and well-worn replacement for the awful mess that is GregorianCalendar, java.util.Date, SimpleTextFormat, and such. Joda-Time works on Android.
LocalTime
Joda-Time offers a LocalTime to represent a time-only value without any date or time zone. This class has the constructor you want, passing hour and minute values.
java.time
The new java.time package built into Java 8 (inspired by Joda-Time) also offers a similar LocalTime class. But Java 8 technology is not available for Android.
Example Code
Here is some example code using Joda-Time 2.4.
LocalTime localTime = new LocalTime( 13, 15 ); // Quarter-hour after 1 PM.
You can apply that LocalTime to a DateTime object. So, Joda-Time already provides everything you are trying to invent. Here is some example code setting today’s date-time to the desired time-of-day unless that has already passed in which case we slide to tomorrow’s date and re-apply our desired time-of-day.
LocalTime localTime = new LocalTime( 13 , 15 ); // Quarter-hour after 1 PM.
System.out.println( "localTime: " + localTime );
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" ); // Or DateTimeZone.UTC
DateTime today = localTime.toDateTimeToday( timeZone );
DateTime now = DateTime.now(); // You may want to pad an bit of extra time in case now is extremely close to midnight (new day).
if ( today.isBefore( now ) ) {
// If the local time in question when applied to today has already past, then
// adjust to tomorrow while accounting for Daylight Saving Time or other anomaly.
DateTime tomorrowInitial = today.plusDays( 1 ); // Get tomorrow by adding 1 day to today.
DateTime tomorrow = localTime.toDateTime( tomorrowInitial ); // DST or other anomaly may mean that tomorrow got adjusted to a different time-of-day. Override with our desired time-of-day.
System.out.println( "tomorrow: " + tomorrow );
// return tomorrow;
}
System.out.println( "today: " + today );
// return today;
When run.
localTime: 13:15:00.000
tomorrow: 2014-10-09T13:15:00.000-04:00
today: 2014-10-08T13:15:00.000-04:00
Best to avoid java.util.Date. But if required, you may convert from Joda-Time.
java.util.Date date = today.toDate(); // Convert from Joda-Time DateTime to java.util.Date.
Maybe I didn't understood all but why not use a Calendar? I mean, you can set the time in a Calendar object.
int hour = 'your hour';
int minute = 'your minute';
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR, hour).
cal.set(Calendar.MINUTE, minute);
Can I instantiate a LocalTime object and set its hours and minutes in
one line of Java code?
Yes, provided that you are using Java 8 (LocalTime seems new in Java 8):
LocalTime time = LocalTime.of(hour, minute);
When you are wondering about the behavior of specific classes, it would behoove you to consult their documentation, in this case, http://docs.oracle.com/javase/8/docs/api/java/time/LocalTime.html. In most cases, you will get your answer faster, plus answers to followup questions.