Can I instantiate a new Date already with a timezone in Java? - java

I need to generate a new Date(); already with the correct time zone, because I need to record the date and time that a new data is received on my server. (I know that you can use the SimpleDateFormat, but it requires to parse a already created string).
I'm using Java + Spring Boot.

java.time
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*.
Solution using java.time, the modern Date-Time API: You can use ZonedDateTime with the applicable ZoneId.
Demo:
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
// Use the applicable ZoneId
ZoneId zoneId = ZoneId.of("Asia/Dubai");
ZonedDateTime now = ZonedDateTime.now(zoneId);
System.out.println(now);
}
}
Output from a sample run:
2021-10-30T02:26:07.471319+04:00[Asia/Dubai]
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time. Check this answer and this answer to learn how to use java.time API with JDBC.
A note on java.util.Date:
A java.util.Date object simply represents an instant on the timeline — a wrapper around the number of milliseconds since the UNIX epoch (January 1, 1970, 00:00:00 GMT). Since it does not hold any timezone information, its toString function applies the JVM's timezone to return a String in the format, EEE MMM dd HH:mm:ss zzz yyyy, derived from this milliseconds value. To get the String representation of the java.util.Date object in a different format and timezone, you need to use SimpleDateFormat with the desired format and the applicable timezone e.g.
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String strDateNewYork = sdf.format(date);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDateUtc = sdf.format(date);
* 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. Note that Android 8.0 Oreo already provides support for java.time.

Use DateFormat. For example,
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = isoFormat.parse("2010-05-23T09:01:02");

Related

Java date format different results

I am looking to understand why this code is giving me different results.
I want to format 2022-10-12T00:00:00.000Z into yyyy-MM-dd format.
Result when I run it online in Java IDE: 2022-10-12
But on my own computer the result is: 2022-10-11
String date = "2022-10-12T00:00:00.000Z";
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
TemporalAccessor ta = DateTimeFormatter.ISO_INSTANT.parse(date);
Instant i = Instant.from(ta);
Date d = Date.from(i);
dateFormat.format(d);
The answer by Louis Wasserman is correct. A couple of important points:
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.
SimpleDateFormat does not have a way to specify a time-zone in the pattern. The way to specify a time-zone with SimpleDateFormat is by calling SimpleDateFormat#setTimeZone(java.util.TimeZone). Without setting time-zone explicitly, SimpleDateFormat uses the system time-zone. You could get the desired result had you done the following
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
dateFormat.format(d);
The solution
I want to format 2022-10-12T00:00:00.000Z into yyyy-MM-dd format
Demo with java.time API:
Since your date-time string is in UTC and you want to get just date part from the UTC date-time:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
String strDate = "2022-10-12T00:00:00.000Z";
// Parse the given text into an OffsetDateTime and format it
String desiredString = OffsetDateTime.parse(strDate)
.format(DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(desiredString);
}
}
Output:
2022-10-12
Learn more about the modern Date-Time API from Trail: Date Time.
If the online IDE is running in a different time zone than you, it might be 10-12 in one time zone and still 10-11 in another. You have specified Z as the time zone of the input, but you have not specified the time zone used in formatting the date.
It may be that Date/SimpleDateFormat don’t support time zone.
You can try using the java.time package:
LocalDate.now()
DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDate.now())

How to convert UTC time format to Date in Java

I have to call a web service which is expecting a Date field but they want it in the following format YYYY-MM-DDThh:mm:ss.sssZ. How can I do this?
I tried the following
OffsetDateTime transactionTime = OffsetDateTime.now(ZoneOffset.UTC);
Date.from(transactionTime.toInstant());
but this didn't work. transactionTime is 2021-06-01T15:11:09.942843400Z, but Date.from converts it to Tue Jun 01 11:11:09 EDT 2021.
BTW, I'm using Java 11
Instant.now().toString()
See that code run live at IdeOne.com.
2021-06-01T15:21:16.783779Z
That format is defined in the ISO 8601 standard. The Z on end means an offset-from-UTC of zero hours-minutes-seconds. Pronounced “Zulu”.
Use java.time.Instant to represent a moment as seen in UTC.
Going the other direction, from text to object.
Instant.parse( "2021-06-01T15:21:16.783779Z" )
If you want only milliseconds, you can lop off any microseconds and nanoseconds by truncating.
Instant.now().truncatedTo( ChronoUnit.MILLIS ) ;
Never use the legacy Date class. Use only the java.time classes.
Use DateTimeFormatter to format the Date-Time object
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
OffsetDateTime transactionTime = OffsetDateTime.now(ZoneOffset.UTC);
String formatted = transactionTime.format(dtf);
System.out.println(formatted);
}
}
Output:
2021-06-01T15:49:45.198Z
Learn more about the modern Date-Time API from Trail: Date Time.
What if I want to use java.util.Date?
For any reason, if you need to convert this object of OffsetDateTime to an object of java.util.Date, you can do so as follows:
Date date = Date.from(transactionTime.toInstant());
Note that a java.util.Date object is not a real Date-Time object like the modern Date-Time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). Since Date does not have timezone information, it applies the JVM's timezone to return the value of Date#toString in the format, EEE MMM dd HH:mm:ss z yyyy calculated from this milliseconds value. If you need to print the Date-Time in a different format and timezone, you will need to use a SimpleDateFormat with the desired format and the timezone set to the applicable one e.g.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDate = sdf.format(date);
System.out.println(strDate);
Output:
2021-06-01T15:49:45.198Z
Some other important notes:
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*.
Most of the symbols that you have used in YYYY-MM-DDThh:mm:ss.sssZ are wrong. Check the description of the symbols from the documentation pages of DateTimeFormatter and SimpleDateFormat.
* 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.

Convert Date string with Time to long date

I have a string with date "10:00 AM 03/29/2011", I need to convert this to a long using Java, I cant use Date because its deprecated and it was not giving me the time correctly.. so i looked online to see how to come about it but still no luck. First time using java.
The problem is you're parsing the data and then messing around with it for no obvious reason, ignoring the documented return value for Date.getYear() etc.
You probably just want something like this:
private static Date parseDate(String text)
throws ParseException
{
SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm a MM/dd/yyyy",
Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
return dateFormat.parse(text);
}
If you really want a long, just use:
private static long parseDate(String text)
throws ParseException
{
SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm a MM/dd/yyyy",
Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
return dateFormat.parse(text).getTime();
}
Note that I'm punting the decision of what to do if the value can't be parsed to the caller, which makes this code more reusable. (You could always write another method to call this one and swallow the exception, if you really want.)
As ever, I'd strongly recommend that you use Joda Time for date/time work in Java - it's a much cleaner API than java.util.Date/Calendar/etc.
java.time
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*.
Solution using java.time, the modern Date-Time API:
Parse the Date-Time string into LocalDateTime.
Convert the LocalDateTime to Instant.
Convert Instant to the Epoch milliseconds.
Demo:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "10:00 AM 03/29/2011";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("h:m a M/d/u", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant();
long epochMillis = instant.toEpochMilli();
System.out.println(epochMillis);
}
}
Output in my timezone, Europe/London:
1301389200000
ONLINE DEMO
Some important notes about this code:
ZoneId.systemDefault() gives you to the JVM's ZoneId.
If 10:00 AM 03/29/2011 belongs to some other timezone, replace ZoneId.systemDefault() with the applicable ZoneId e.g. ZoneId.of("America/New_York").
If 10:00 AM 03/29/2011 is in UTC, you can do either of the following:
get the Instant directly as ldt.toInstant(ZoneOffset.UTC) or
replace ZoneId.systemDefault() with ZoneId.of("Etc/UTC") in this code.
The timezone of the Ideone server (the online IDE) is UTC whereas London was at an offset of +01:00 hours on 03/29/2011 and hence the difference in the output from my laptop and the one you see in the ONLINE DEMO. Arithmetic: 1301389200000 + 60 * 60 * 1000 = 1301392800000
Learn more about the modern Date-Time API from Trail: Date Time.
* 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.

How to convert currentTimeMillis to a date in Java?

I have milliseconds in certain log file generated in server, I also know the locale from where the log file was generated, my problem is to convert milliseconds to date in specified format.
The processing of that log is happening on server located in different time zone. While converting to "SimpleDateFormat" program is taking date of the machine as such formatted date do not represent correct time of the server. Is there any way to handle this elegantly ?
long yourmilliseconds = 1322018752992l;
//1322018752992-Nov 22, 2011 9:25:52 PM
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS",Locale.US);
GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("US/Central"));
calendar.setTimeInMillis(yourmilliseconds);
System.out.println("GregorianCalendar -"+sdf.format(calendar.getTime()));
DateTime jodaTime = new DateTime(yourmilliseconds,
DateTimeZone.forTimeZone(TimeZone.getTimeZone("US/Central")));
DateTimeFormatter parser1 = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss,SSS");
System.out.println("jodaTime "+parser1.print(jodaTime));
Output:
Gregorian Calendar -2011-11-23 08:55:52,992
jodaTime 2011-11-22 21:25:52,992
You may use java.util.Date class and then use SimpleDateFormat to format the Date.
Date date=new Date(millis);
We can use java.time package (tutorial) - DateTime APIs introduced in the Java SE 8.
var instance = java.time.Instant.ofEpochMilli(millis);
var localDateTime = java.time.LocalDateTime
.ofInstant(instance, java.time.ZoneId.of("Asia/Kolkata"));
var zonedDateTime = java.time.ZonedDateTime
.ofInstant(instance,java.time.ZoneId.of("Asia/Kolkata"));
// Format the date
var formatter = java.time.format.DateTimeFormatter.ofPattern("u-M-d hh:mm:ss a O");
var string = zonedDateTime.format(formatter);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeStamp);
int mYear = calendar.get(Calendar.YEAR);
int mMonth = calendar.get(Calendar.MONTH);
int mDay = calendar.get(Calendar.DAY_OF_MONTH);
tl;dr
Instant.ofEpochMilli( 1_322_018_752_992L ) // Parse count of milliseconds-since-start-of-1970-UTC into an `Instant`.
.atZone( ZoneId.of( "Africa/Tunis" ) ) // Assign a time zone to the `Instant` to produce a `ZonedDateTime` object.
Details
The other answers use outmoded or incorrect classes.
Avoid the old date-time classes such as java.util.Date/.Calendar. They have proven to be poorly designed, confusing, and troublesome.
java.time
The java.time framework comes built into Java 8 and later. Much of the functionality is backported to Java 6 & 7 and further adapted to Android. Made by the some of the same folks as had made Joda-Time.
An Instant is a moment on the timeline in UTC with a resolution of nanoseconds. Its epoch is first moment of 1970 in UTC.
Assuming your input data is a count of milliseconds from 1970-01-01T00:00:00Z (not clear in the Question), then we can easily instantiate an Instant.
Instant instant = Instant.ofEpochMilli( 1_322_018_752_992L );
instant.toString(): 2011-11-23T03:25:52.992Z
The Z in that standard ISO 8601 formatted string is short for Zulu and means UTC.
Apply a time zone using a proper time zone name, to get a ZonedDateTime.
ZoneId zoneId = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( zoneId );
See this code run live at IdeOne.com.
Asia/Kolkata time zone ?
I am guessing your are had an India time zone affecting your code. We see here that adjusting into Asia/Kolkata time zone renders the same time-of-day as you report, 08:55 which is five and a half hours ahead of our UTC value 03:25.
2011-11-23T08:55:52.992+05:30[Asia/Kolkata]
Default zone
You can apply the current default time zone of the JVM. Beware that the default can change at any moment during runtime. Any code in any thread of any app within the JVM can change the current default. If important, ask the user for their desired/expected time zone.
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
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.
With a JDBC driver complying with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings or 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.
The easiest way to do this is to use the Joda DateTime class and specify both the timestamp in milliseconds and the DateTimeZone you want.
I strongly recommend avoiding the built-in Java Date and Calendar classes; they're terrible.
If the millis value is number of millis since Jan 1, 1970 GMT, as is standard for the JVM, then that is independent of time zone. If you want to format it with a specific time zone, you can simply convert it to a GregorianCalendar object and set the timezone. After that there are numerous ways to format it.
My Solution
public class CalendarUtils {
public static String dateFormat = "dd-MM-yyyy hh:mm";
private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);
public static String ConvertMilliSecondsToFormattedDate(String milliSeconds){
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(Long.parseLong(milliSeconds));
return simpleDateFormat.format(calendar.getTime());
}
}
Easiest way:
private String millisToDate(long millis){
return DateFormat.getDateInstance(DateFormat.SHORT).format(millis);
//You can use DateFormat.LONG instead of SHORT
}
I do it like this:
static String formatDate(long dateInMillis) {
Date date = new Date(dateInMillis);
return DateFormat.getDateInstance().format(date);
}
You can also use getDateInstance(int style) with following parameters:
DateFormat.SHORT
DateFormat.MEDIUM
DateFormat.LONG
DateFormat.FULL
DateFormat.DEFAULT
The SimpleDateFormat class has a method called SetTimeZone(TimeZone) that is inherited from the DateFormat class. http://docs.oracle.com/javase/6/docs/api/java/text/DateFormat.html
You can try java.time api;
Instant date = Instant.ofEpochMilli(1549362600000l);
LocalDateTime utc = LocalDateTime.ofInstant(date, ZoneOffset.UTC);
Below is my solution to get date from miliseconds to date format. You have to use Joda Library to get this code run.
import java.util.GregorianCalendar;
import java.util.TimeZone;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class time {
public static void main(String args[]){
String str = "1431601084000";
long geTime= Long.parseLong(str);
GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("US/Central"));
calendar.setTimeInMillis(geTime);
DateTime jodaTime = new DateTime(geTime,
DateTimeZone.forTimeZone(TimeZone.getTimeZone("US/Central")));
DateTimeFormatter parser1 = DateTimeFormat.forPattern("yyyy-MM-dd");
System.out.println("Get Time : "+parser1.print(jodaTime));
}
}
public static String getFormatTimeWithTZ(Date currentTime) {
SimpleDateFormat timeZoneDate = new SimpleDateFormat("EEE, dd-MM-yyyy hh:mm a", Locale.getDefault());
return timeZoneDate.format(currentTime);
}
Output is
Mon,01-03-2021 07:37 PM
and
public static String getFormatTimeWithTZ(Date currentTime) {
SimpleDateFormat timeZoneDate = new SimpleDateFormat("EEE, dd-MM-yyyy HH:mm ", Locale.getDefault());
return timeZoneDate.format(currentTime);
}
output is
Mon,01-03-2021 19:37
if you do not want the Days Then Remove EEE,
if you do not want the Date Then Remove dd-MM-yyyy
If you want Time in Hour, Minutes, Second, Millisecond then Use HH:mm:ss.SSS
and Call this method where you want
getFormatTimeWithTZ(Mydate)
where
Date Mydate = new Date(System.currentTimeMillis());
public static LocalDateTime timestampToLocalDateTime(Long timestamp) {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), TimeZone.getDefault().toZoneId());
}

server time zone java conversion

Ok, so I've pretty much tried everything. I bet it's something really simple but I can't seem to get a hold of it.
The server sends me the time, which is epoch. However when I put this into a date object it seems to automatically pick up the time zone and it adds +3 to the server time. So if the gmt time is 00.00, it says its 03.00.
I also need to add a timezone of my own. Let's say the epoch time is 00.00 again, it should read 10.00 after I add the timezone.
any help would be much appreciated. Thank you
"It seems to add" - I suspect you're using Date.toString() which does indeed use the local time zone. The Date object itself is effectively in UTC though. Use DateFormat to perform the conversion to a string instead, and you can specify which time zone to use. You may also need to use Calendar - it depends what you're trying to do.
(Alternatively, use Joda Time in the first place, which is a better API. It may be a little bulky for your Android project though. I wouldn't be surprised if there were a "Joda Time lite" project around somewhere for precisely this sort of thing...)
EDIT: Quick sample, although it's not entirely clear what you need...
long millis = getMillisFromServer();
Date date = new Date(millis);
DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
format.setTimeZone(customTimeZone);
String formatted = format.format(date);
java.time
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*.
Also, quoted below is a notice from the home page of Joda-Time:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
Solution using java.time, the modern Date-Time API:
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
long millis = 1316391494L;
Instant instant = Instant.ofEpochMilli(millis);
System.out.println(instant);
// The same instant at a specific timezone
ZonedDateTime zdt = instant.atZone(ZoneId.of("Australia/Brisbane"));
System.out.println(zdt);
}
}
Output:
1970-01-16T05:39:51.494Z
1970-01-16T15:39:51.494+10:00[Australia/Brisbane]
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
What went wrong with your code?
A java.util.Date object simply represents an instant on the timeline — a wrapper around the number of milliseconds since the UNIX epoch (January 1, 1970, 00:00:00 GMT). Since it does not hold any timezone information, its toString function applies the JVM's timezone to return a String in the format, EEE MMM dd HH:mm:ss zzz yyyy, derived from this milliseconds value. To get the String representation of the java.util.Date object in a different format and timezone, you need to use SimpleDateFormat with the desired format and the applicable timezone e.g.
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) {
long millis = 1316391494L;
Date date = new Date(millis);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX[zzzz]", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDateUtc = sdf.format(date);
System.out.println(strDateUtc);
sdf.setTimeZone(TimeZone.getTimeZone("Australia/Brisbane"));
String strDateBrisbane = sdf.format(date);
System.out.println(strDateBrisbane);
}
}
Output:
1970-01-16T05:39:51.494Z[Coordinated Universal Time]
1970-01-16T15:39:51.494+10:00[Australian Eastern Standard Time]
ONLINE DEMO
* 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.

Categories