I need to replace SimpleDataFormat with Java 8 DateTimeFormatter. Below is the code with SimpleDateFormat.
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(source);
Now I need to change it to DateTimeFormatter. I tried as below
LocalDateTime ld = LocalDateTime.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
Date startdate = dtf.parse(dtf);
Now this is generating exception.
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate localDate = LocalDate.parse("2017-02-11", dtf);
System.out.println(localDate.toString());
if you want Date object from LocalDate,the following works
Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
As #JonSkeet advised, If you're using Java 8 you should probably avoid java.util.Date altogether
If looking for equivalent of your sdf in DateTimeFormatter try DateTimeFormatter.ISO_LOCAL_DATEExplore the DateTimeFormatter class for more formats.
LocalDateTime time = LocalDateTime.now();
time.format(DateTimeFormatter.ISO_LOCAL_DATE);
Use LocalDate instead of LocalDateTime if intrested in Date only.
tl;dr
java.util.Date.from(
LocalDate.parse( "2017-01-23" )
.atStartOfDay( ZoneId.of( "America/Montreal" ) )
.toInstant()
)
No need of formatting pattern
No formatting pattern needed. Your input string happens to be in standard ISO 8601 format. These standard formats are used by default in the java.time classes for parsing and generating strings.
LocalDate
Use LocalDate for a date-only value, without time-of-day and without time zone.
LocalDate ld = LocalDate.parse( "2017-01-23" );
ZonedDateTime
If you want a date-time, let java.time determine the first moment of the day. Do not assume that first moment is 00:00:00.
Determining first moment of the day requires a time zone. The date varies around the globe by zone.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ld.atStartOfDay( z );
If you want to perceive that moment through the lens of UTC, extract an Instant object.
Instant instant = zdt.toInstant();
The Instant is equivalent to the old legacy class java.util.Date. Both represent a moment on the timeline in UTC. The modern class has a finer resolution, nanoseconds rather than milliseconds.
Avoid java.util.Date
As others mentioned, you should stick with the modern java.time classes. But if you must, you can convert. Look to new methods added to the old classes.
java.util.Date d = java.util.Date.from( instant ) ;
One way of doing it would be -
LocalDateTime ld = LocalDateTime.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String date = ld.format(dtf);
Related
I'm trying to make a code that tells me how many days left for me to go college, but I am not able to do it with the current date. I can easily make it by setting a date, but I want the current date, so I have to use the calendar method, but can't do math using it.
My code:
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Calendar calendar = Calendar.getInstance();
Date start = sdf.parse("10/06/2022");
System.out.println(start - calendar.getTime());
tl;dr
ChronoUnit.DAYS.between(
LocalDate.now( ZoneId.of( "Pacific/Auckland" ) ) ,
LocalDate.parse( "10/06/2022" , DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) )
)
Details
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310. Never use Date/Calendar.
Also, you are attempting to use a date-time class representing a date with time-of-day as seen in UTC (offset of zero) to hold a date-only value. Square peg, round hole.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) ;
LocalDate graduationDate = LocalDate.parse( "10/06/2022" , f ) ;
Determine today's date. That requires a time zone. For any given moment, the date varies around the globe by time zone.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ; // Or ZoneId.systemDefault()
LocalDate today = LocalDate.now( z ) ;
Calculate elapsed time using java.time.temporal.ChronoUnit.
long days = ChronoUnit.DAYS.between( today , graduationDate ) ;
See this code run live at IdeOne.com.
graduationDate: 2022-06-10
today: 2022-03-05
days: 97
Tip: Learn about the ISO 8601 standard for exchanging date-time values as text.
Calendar calendar = Calendar.getInstance();
Calendar collegeDate = Calendar.getInstance();
collegeDate.set(Calendar.DATE,10);
collegeDate.set(Calendar.MONTH, 5);
collegeDate.set(Calendar.YEAR, 2022);
System.out.println(Duration.between(calendar.toInstant(), collegeDate.toInstant()).toDays());
You can try this
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Calendar calendar = Calendar.getInstance();
Date start = sdf.parse("10/06/2022");
long dif = Math.abs(calendar.getTimeInMillis() - start.getTime());
long result = TimeUnit.DAYS.convert(dif, TimeUnit.MILLISECONDS);
System.out.println(result);
I want to convert a timestamp (which is in GMT) to a local date and time.
This is what I have implemented so far, but it is giving me wrong month
Timestamp stp = new Timestamp(1640812878000L);
Calendar convertTimestamp = convertTimeStamp(stp,"America/Phoenix");
System.out.println(convertTimestamp.getTime());
public static Calendar convertTimeStamp( Timestamp p_gmtTime, String p_timeZone) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy HH:MM:SS a", Locale.ENGLISH);
DateFormat formatter = DateFormat.getDateTimeInstance();
if (p_timeZone != null) {
formatter.setTimeZone(TimeZone.getTimeZone(p_timeZone));
} else {
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
}
String gmt_time = formatter.format(p_gmtTime);
Calendar cal = Calendar.getInstance();
cal.setTime(sdf.parse(gmt_time));
return cal;
}
Any help would be appreciated.
You cannot convert a timestamp to another timezone, cause timestamps are always GMT, they are a given moment in the line of time in the universe.
We humans are used to local time on our planet, so a timestamp can be formatted to be more human readable, and in that context it is converted to a local timezone.
Using legacy java.util.* packages, this is done as follows:
DateFormat tzFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
tzFormat.setTimeZone(TimeZone.getTimeZone("CET")); // Use whatever timezone
System.out.println(tzFormat.format(date));
If you need to make "math" over the timestamp on local timezone (like, tomorrow at 8:00 local timezone), then the situation is more complex.
To do this you can resort to a number of hacks (like parsing or modifying the string obtained with the method above), or use the new Java date & time classes that have a specific class to deal with date and time in local time zones:
Instant timestamp = Instant.ofEpochMilli(inputValue);
ZonedDateTime romeTime = timestamp.atZone(ZoneId.of("Europe/Rome"));
Note how this second example uses "Europe/Rome" and not generically "CET". This is very important if you're planning to deal with timezones where DST is used, cause the DST change day (or if they use DST or not) may change from country to country even if they are in the same timezone.
tl;dr
Instant
.ofEpochMilli( // Parse a count of milliseconds since 1970-01-01T00:00Z.
1_640_812_878_000L
) // Returns a `Instant` object.
.atZone( // Adjust from UTC to a time zone. Same moment, same point on the timeline, different wall-clock time.
ZoneId.of( "America/Phoenix" )
) // Returns a `ZonedDateTime` object.
.format( // Generat text representing the date-time value kept within that `ZonedDateTime` object.
DateTimeFormatter
.ofLocalizedDateTime( FormatStyle.MEDIUM )
.withLocale( Locale.US )
) // Returns a `String` object.
See this code run live at IdeOne.com.
Dec 29, 2021, 2:21:18 PM
Details
You are using terrible old date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310. Never use Timestamp, Calendar, Date, SimpleDateFormat, etc.
Use the Instant class to represent a moment as seen in UTC, with an offset of zero hours-minutes-seconds.
long millisecondsSinceBeginningOf1970InUtc = 1_640_812_878_000L ;
Instant instant = Instant.ofEpochMilli( millisecondsSinceBeginningOf1970InUtc ) ;
Specify the time zone in which you are interested.
ZoneID z = ZoneId.of( "Africa/Tunis" ) ;
Adjust from offset of zero to that time zone to produce a ZonedDateTime object.
ZonedDateTime zdt = instant.atZone( z ) ;
Generate text representing that moment by automatically localizing. Use a Locale to specify the human language to use in translation as well as a culture to use in deciding abbreviation, capitalization, order of elements, and so on.
Locale locale = Locale.JAPAN ; // Or Locale.US, Locale.ITALY, etc.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.LONG ).withLocale( locale ) ;
String output = zdt.format( f ) ;
All of this has been addressed many times on Stack Overflow. Search to learn more.
I have a java component to format the date that I retrieve. Here is my code:
Format formatter = new SimpleDateFormat("yyyyMMdd");
String s = "2019-04-23 06:57:00.0";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss.S");
try
{
Date date = simpleDateFormat.parse(s);
System.out.println("Formatter: "+formatter.format(date));
}
catch (ParseException ex)
{
System.out.println("Exception "+ex);
}
The code works great as long as the String s has the format "2019-04-23 06:57:00.0";
My Question is, how to tweak this code so it will work for below scenarios ex,
my s string may have values like
String s = "2019-04-23 06:57:00.0";
or
String s = "2019-04-23 06:57:00";
Or
String s = "2019-04-23";
right now it fails if I don't pass the ms.. Thanks!
Different types
String s = "2019-04-23 06:57:00";
String s = "2019-04-23";
These are two different kinds of information. One is a date with time-of-day, the other is simply a date. So you should be parsing each as different types of objects.
LocalDateTime.parse
To comply with the ISO 8601 standard format used by default in the LocalDateTime class, replace the SPACE in the middle with a T. I suggest you educate the publisher of your data about using only ISO 8601 formats when exchanging date-time values as text.
LocalDateTime ldt1 = LocalDateTime.parse( "2019-04-23 06:57:00".replace( " " , "T" ) ) ;
The fractional second parses by default as well.
LocalDateTime ldt2 = LocalDateTime.parse( "2019-04-23 06:57:00.0".replace( " " , "T" ) ) ;
See this code run live at IdeOne.com.
ldt1.toString(): 2019-04-23T06:57
ldt2.toString(): 2019-04-23T06:57
LocalDate.parse
Your date-only input already complies with ISO 8601.
LocalDate ld = LocalDate.parse( "2019-04-23" ) ;
See this code run live at IdeOne.com.
ld.toString(): 2019-04-23
Date with time-of-day
You can strip out the time-of-day from the date.
LocalDate ld = ldt.toLocalDate() ;
And you can add it back in.
LocalTime lt = LocalTime.parse( "06:57:00" ) ;
LocalDateTime ldt = ld.with( lt ) ;
Moment
However, be aware that a LocalDateTime does not represent a moment, is not a point on the timeline. Lacking the context of a time zone or offset-from-UTC, a LocalDateTime cannot hold a moment, as explained in its class JavaDoc.
For a moment, use the ZonedDateTime, OffsetDateTime, or Instant classes. Teach the publisher of your data to include the offset, preferably in UTC.
Avoid legacy date-time classes
The old classes SimpleDateFormat, Date, and Calendar are terrible, riddled with poor design choices, written by people not skilled in date-time handling. These were supplanted years ago by the modern java.time classes defined in JSR 310.
In case of you have optional parts in pattern you can use [ and ].
For example
public static Instant toInstant(final String timeStr){
final DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("yyyy-MM-dd HH[:mm[:ss[ SSSSSSSS]]]")
.withZone(ZoneId.of("UTC"));
try {
return Instant.from(formatter.parse(timeStr));
}catch (DateTimeException e){
final DateTimeFormatter formatter2 = DateTimeFormatter
.ofPattern("yyyy-MM-dd")
.withZone(ZoneId.of("UTC"));
return LocalDate.parse(timeStr, formatter2).atStartOfDay().atZone(ZoneId.of("UTC")).toInstant();
}
}
cover
yyyy-MM-dd
yyyy-MM-dd HH
yyyy-MM-dd HH:mm
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd HH:mm:ss SSSSSSSS
I'm trying to convert the created_utc date from Reddit's json to a Date object, but I keep getting an "Unparceable" error. An example of their dates is: created_utc": 1.43701862E9, which I'm told is a unix timestamp.
From my research this code should convert it:
String date = "1.43701862E9";
java.util.Date time = new java.util.Date((long)date*1000);
but obviously I'm getting an error on multiplying the date by 1000.
This is the code I normally use to convert string dates:
String date = "1.43701862E9";
Calendar cal = Calendar.getInstance(TimeZone.getDefault());
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
format.parse(date);
This should work for you:
public static void main(String[] args) {
String date = "1.43701862E9";
java.util.Date time = new java.util.Date(Double.valueOf(date).longValue()*1000);
System.out.println(time);
}
Output:
Wed Jul 15 23:50:20 EDT 2015
Since you're using scientific notation you can't parse the String using the Long class: Long.parseLong(String s) (Nor can you simply cast a String, as you're trying). Instead, I used the Double.valueOf() method and preserve the Long using .longValue()
The answer by Trobbins is correct but old-school. I lifted that Answer’s math, and used the new java.time classes.
java.time
In Java 8 and later, you can use the new java.time package which supplants the troublesome old java.util.Date/.Calendar classes. (Tutorial)
String input = "1.43701862E9";
long milliSinceEpoch = Double.valueOf( input ).longValue() * 1_000L ;
Instant instant = Instant.ofEpochMilli( milliSinceEpoch ) ;
ZoneId zoneId = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId ) ;
Try to avoid java.util.Date/.Calendar, but if need be you can convert.
java.util.Date date = Date.from( zdt.toInstant() ); // Or… Date.from( instant );
java.util.Calendar calendar = GregorianCalendar.from( zdt );
SimpleDateFormat parser = new SimpleDateFormat("HH:mm");
Date time1 = parser.parse("7:30");
Now if I want to add 2 more hours to time1, like:
7:30 + 2 = 9:30
how do I add the 2 hours?
java.util.Date is deprecated, you should use java.util.Calendar instead.
SimpleDateFormat parser = new SimpleDateFormat("HH:mm");
Date myDate = parser.parse("7:30");
Calendar cal =Calendar.getInstance();
cal.setTime(myDate);
cal.add(Calendar.HOUR_OF_DAY,2); // this will add two hours
myDate = cal.getTime();
And even better solution is to use Joda Time - Java date and time API.
From their website - Joda-Time provides a quality replacement for the Java date and time classes.
Convert java.util.Date into java.util.Calendar Object and use Calendar.add() method to add Hours
SimpleDateFormat parser = new SimpleDateFormat("HH:mm");
Date time1 = parser.parse("7:30");
Calendar cal =Calendar.getInstance();
cal.setTime(time1);
cal.add(Calendar.Hour_Of_Day, 2);
time1 =cal.getTime();
System.out.println(parser.format(time1));//returns 09:30
tl;dr
LocalTime.parse( "07:30" ).plusHours( 2 )
…or…
ZonedDateTime.now( ZoneId.of( " Pacific/Auckland" ) )
.plusHours( 2 )
java.time
The old date-time classes such as java.util.Date, .Calendar, and java.text.SimpleDateFormat should be avoided, now supplanted by the java.time classes.
LocalTime
For a time-of-day only value, use the LocalTime class.
LocalTime lt = LocalTime.parse( "07:30" );
LocalTime ltLater = lt.plusHours( 2 );
String output = ltLater.toString(); // 09:30
Instant
For a given java.util.Date, convert to java.time using new methods added to the old classes. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds.
Instant instant = myUtilDate.toInstant();
Or capture current moment in UTC as an Instant.
Instant instant = Instant.now();
Add two hours as seconds. The TimeUnit class can convert hours to seconds.
long seconds = TimeUnit.HOURS.toSeconds( 2 );
Instant instantLater = instant.plusSeconds( seconds );
ZonedDateTime
To view in the wall-clock time of some community, apply a time zone. Apply a ZoneId to get a ZonedDateTime object.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
You can add hours. The ZonedDateTime class handles anomalies such as Daylight Saving Time.
ZonedDateTime zdtLater = zdt.plusHours( 2 );
Duration
You can represent that two hours as an object.
Duration d = Duration.ofHours( 2 ) ;
ZonedDateTime zdtLater = zdt.plus( d ) ;