How to compare Two date in android? - android

I have a date from server in the format yyyy-mm-dd HH:mm:ss .I have the current time in millis by System.currentTimeMillis(). I want to compare both dates and see if date received from server is future date and if it is so schedule an alarm for the future date.
so my question how to compare this 2 different format dates and how to get remaining time (future- current) so as to schedule the alarm.
Edit:
I already tried parsing the date in millis but it doesnt return value as same format as System.currentTimeMillis(). so it fails

You can parse the yyyy-mm-dd HH:mm:ss date thanks to DateFormat class (e.g. the SimpleDateFormat class). This operation will return a Date object.
You can also create a Date object from current time in milliseconds.
When you have both objects you can compare them thanks to compareTo method.
For instance the following code:
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date parsed = sdf.parse("2016-03-10 22:05:20");
Date now = new Date(System.currentTimeMillis()); // 2016-03-10 22:06:10
System.out.println(parsed.compareTo(now));
} catch (Exception e) {
e.printStackTrace();
}
will print -1, which means that parsed is before now.
EDIT:
Here it is the code of a simple but useless application that makes use of AlarmManager.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d("TAG", "From intent: "+getIntent().getStringExtra("MyEXTRA"));
}
#Override
protected void onResume() {
super.onResume();
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
long parsedMillis = sdf.parse("2016-03-10 22:54:30").getTime();
long now = System.currentTimeMillis(); // 22:54:15
if (parsedMillis > now) {
Log.d("TAG", "In the future!");
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, MyActivity.class);
intent.putExtra("MyEXTRA", "From alarm");
PendingIntent broadcast = PendingIntent.getActivity(this, 0, intent, 0);
am.setExact(AlarmManager.RTC_WAKEUP, parsedMillis, broadcast);
} else {
Log.d("TAG", "In the past...");
}
} catch (Exception e) {
e.printStackTrace();
}
}
In the LogCat you will see:
03-10 22:54:20.925 3946-3946/com.example.myapp D/TAG﹕ From intent: null
03-10 22:54:21.227 3946-3946/com.example.myapp D/TAG﹕ In the future!
03-10 22:54:30.513 3946-3946/com.example.myapp D/TAG﹕ From intent: From alarm
03-10 22:54:30.577 3946-3946/com.example.myapp D/TAG﹕ In the past...
The last line is printed because the alarm causes the activity to be relaunched, hence the onResume will be called another time and System.currentTimeMillis() will be greater than the hardcoded time. As you can see, however, the alarm is correctly fired at the scheduled time.
Moreover you should consider edge cases: if parsedMillis is greater than now by only a few milliseconds, you could set an alarm that will never be fired because it is set in the past. This happens because the OS needs some time to execute your code, so you should check that parsedMillis > now + DELTA, where DELTA is a reasonable amout of time that depends on the code you execute between System.currentTimeMillis() and am.setExact(...).

I recommend you do it using the modern date-time API*.
A simple way to do it using the modern API is to parse the server's date-time string into ZonedDateTime using the server's timezone and convert the resulting object into Instant which you can compare with Instant#now.
Demo:
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
// An arbitrary date for demo
String strDateTime = "2021-05-09 10:20:30";
// Replace JVM's default time zone, ZoneId.systemDefault() with applicable time
// zone e.g. ZoneId.of("America/New_York")
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH)
.withZone(ZoneId.systemDefault());
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
Instant instantServer = zdt.toInstant();
Instant now = Instant.now();
if (instantServer.isBefore(now))
System.out.println("The server time is before the current time.");
else if (instantServer.isAfter(now))
System.out.println("The server time is after the current time.");
else
System.out.println("The server time is the same as the current time.");
}
}
Output when I run it now in my system:
The server time is before the current time.
Learn more about the 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.

Related

How to convert time stamp to get exact milliseconds difference in Android?

I have time in this format:
If I have times like Y1 = 05:41:54.771 and Y2 = 05:42:03.465, I want to have exact difference in milliseconds. For the above example the exact millisecond difference would be "6693 milliseconds". How do I achieve this?
Date date = new Date(timestamp);
DateFormat format = new SimpleDateFormat("hh:mm:ss.SSS",Locale.getDefault());
}
The date-time API of java.util 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.
Using the modern date-time API:
import java.time.Duration;
import java.time.LocalTime;
public class Main {
public static void main(String[] args) {
long millisBetween = Duration.between(LocalTime.parse("05:41:54.771"), LocalTime.parse("05:42:03.465"))
.toMillis();
System.out.println(millisBetween);
}
}
Output:
8694
Learn more about the modern date-time API from Trail: Date Time.
Using the legacy API:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
DateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS", Locale.ENGLISH);
long millisBetween = sdf.parse("05:42:03.465").getTime() - sdf.parse("05:41:54.771").getTime();
System.out.println(millisBetween);
}
}
Output:
8694
Some important notes about this solution:
Without a date, SimpleDateFormat parses the time string with a date of January 1, 1970 GMT.
Date#getTime returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object.
Use H instead of h for a time value in 24-Hour format.
You are in the right direction. Using the DateFormat's parse() method you can get a Date object. Then convert it to instant and get the millis since epoch. Finally it's a simple subtraction.
DateFormat format = new SimpleDateFormat("hh:mm:ss.SSS", Locale.getDefault());
try {
Instant y1 = format.parse("05:41:54.771").toInstant();
Instant y2 = format.parse("05:42:03.465").toInstant();
long diffMillis = y2.toEpochMilli() - y1.toEpochMilli();
System.out.println(diffMillis);
} catch (ParseException e) {
throw new RuntimeException(e);
}
The line of code you have provided is a DateFormat object that takes a date and formats it into a string representation. It doesn't have any actual data stored in it. You want to make a comparison on the actual date object, not the formatter.
There are a few different ways to store time, but a common way to store timestamps is as a Long. Since longs are numbers, you can do comparison and math just like an Int:
Long startTime = System.currentTimeMillis();
// Do some long task here that we want to know the duration of
Long endTime = System.currentTimeMillis();
Long difference = endTime - startTime;
Alternatively, there are libraries and tools for dealing with structured time data that may have other ways of storing timestamps and comparing them, however this is a quick example of a common simple implementation if you just need to quickly compare two timestamps.

Format Date to display dd/MM/yyyy [duplicate]

This question already has answers here:
Parsing ISO 8601 date format like 2015-06-27T13:16:37.363Z in Java [duplicate]
(2 answers)
Closed 5 years ago.
I have a method to format date i get from the server in this format 2018-01-18T13:52:49.107Z. I want to convert this format to only show the day, month and year but it doesnt work. How do i translate this response from the server to show the date format.
This is my method below:
private String formatDate(String dateString) {
try {
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss.S" );
Date d = sd.parse(dateString);
sd = new SimpleDateFormat("dd/MM/yyyy");
return sd.format(d);
} catch (ParseException e) {
}
return "";
}
Try to change the date formate with yyyy-MM-dd'T'HH:mm:ss.SSS
private String formatDate(String dateString) {
try {
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS" );
Date d = sd.parse(dateString);
sd = new SimpleDateFormat("dd/MM/yyyy");
return sd.format(d);
} catch (ParseException e) {
}
return "";
}
Try this
private String formatDate(String dateString) {
SimpleDateFormat input = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy");
Date d = null;
try {
d = input.parse(dateString);
} catch (ParseException e) {
e.printStackTrace();
}
String formatted = output.format(d);
Log.i("DATE", "" + formatted);
return formatted;
}
OUTPUT
Convert input string into a date
DateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
Date date = inputFormat.parse(inputString);
Format date into output format
DateFormat outputFormat = new SimpleDateFormat("dd-MM-yyyy");
String outputString = outputFormat.format(date);
Here is the code to achieve this:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class DateForm {
public static void main(String args[]) {
String formatted = convertDateToReadable("2018-01-18T13:52:49.107Z");
System.out.println("formatted = " + formatted);
}
public static String convertDateToReadable(String dateStr) {
DateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.ENGLISH);
DateFormat outputFormat = new SimpleDateFormat("yyyy/MM/dd");
Date formattedDate = null;
try {
formattedDate = inputFormat.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
String formattedDateStr = outputFormat.format(formattedDate);
return formattedDateStr;
}
}
Output = formatted = 2018/01/18
This is ISO-DATE time format.
ISO dates can be written with added hours, minutes, and seconds (YYYY-MM-DDTHH:MM:SSZ)
Date and time is separated with a capital T.
UTC time is defined with a capital letter Z.
private String formatDate(String dateString) {
try {
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ" );
Date d = sd.parse(dateString);
sd = new SimpleDateFormat("dd/MM/yyyy");
return sd.format(d);
} catch (ParseException e) {
}
return "";
}
TL:DR
private static final DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("dd/MM/yyyy");
private static String formatDate(String dateString) {
return Instant.parse(dateString)
.atZone(ZoneId.of("Pacific/Tarawa"))
.format(dateFormatter);
}
You need to specify time zone
Given your string 2018-01-18T13:52:49.107Z the method above returns 19/01/2018. 19?? Yes, when it’s 13:52 UTC it’s already the following day on the Tarawa Atoll. And since it is never the same date everywhere on Earth, you need to specify the time zone in which you want the date. So please substitute your desired time zone if it didn’t happen to be Pacific/Tarawa. For example Africa/Maputo or Asia/Sakhalin. Then you will get the date in that zone, formatted as specified. It will not always coincide with the date in the string (in this case Jan 18, 2018) because the string gives the date and time in UTC. To use the user’s time zone you may try specifying ZoneId.systemDefault(). This will use the JVM’s time zone setting. Beware that it is fragile, the setting may be changed under your feet from other parts of your program or other programs running in the same JVM. If you did intend to have the date in UTC as in the string, use:
return Instant.parse(dateString)
.atOffset(ZoneOffset.UTC)
.format(dateFormatter);
Now the result is guaranteed to be 18/01/2018.
java.time
I am using java.time, the modern Java date and time API. I recommend you do the same. The Date class is long outdated, and SimpleDateFormat is not only that, it is also notoriously troublesome. The modern API is so much nicer to work with.
Question: Can I use java.time on Android?
Yes, you can use java.time on Android. It just requires at least Java 6.
In Java 8 and later and on newer Android devices the modern API comes built-in.
In 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.
What went wrong in your code?
The main error in your method (worse that using the outdated classes) is between the following two lines!
} catch (ParseException e) {
}
An empty catch block swallows exceptions so you don’t get to see what goes wrong. Never do that. Try for example:
} catch (ParseException e) {
System.out.println("Message: " + e.getMessage());
System.out.println("Error offset: " + e.getErrorOffset());
if (e.getErrorOffset() != -1) {
System.out.println("Error text: " + dateString.substring(e.getErrorOffset()));
}
}
This prints:
Message: Unparseable date: "2018-01-18T13:52:49.107Z"
Error offset: 5
Error text: 01-18T13:52:49.107Z
So your formatter cannot parse 01, the month. Check the documentation, it says about month: “ If the number of pattern letters is 3 or more, the month is interpreted as text;…”. So lets try MM instead of MMM in the format pattern string. Now we get:
Message: Unparseable date: "2018-01-18T13:52:49.107Z"
Error offset: 10
Error text: T13:52:49.107Z
The T is offending. Of course, it’s not in the pattern string. To indicate that a literal letter is part of the format, enclose it apostrophes: yyyy-MM-dd'T'HH:mm:ss.S. Next time your method returns:
18/01/2018
Are we through? I’d say not. You are ignoring the Z at the end. It means offset 0 from UTC or “Zulu time zone”. By ignoring it, you are parsing the date-time string as a date-time in your JVM’s default time zone, which gives an incorrect time. In newer Java versions the Z can be parsed using the format pattern letter uppercase X, either one, two or three of them. Try yyyy-MM-dd'T'HH:mm:ss.SXXX:
Message: Unparseable date: "2018-01-18T13:52:49.107Z"
Error offset: 22
Error text: 7Z
It seems that one S matches two digits, 10, but not the third decimal, 7. I don’t know why, but let’s put three, SSS for three decimals: yyyy-MM-dd'T'HH:mm:ss.SSSXXX. Now it works.
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.timeto 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.

Getting Current date and time

I tried to access current datetime in android application as follows :
Calendar c = Calendar.getInstance();
int seconds = c.get(Calendar.SECOND);
//long time = System.currentTimeMillis();
Date date2 = new Date(seconds);
Log.d(">>>>>>>Current Date : ",""+date2);
It gives me date and time with the year 1970 as follows :
>>>>>>>Current Date :﹕ Thu Jan 01 05:30:00 GMT+05:30 1970
but, It should be 2015 instead of 1970.
What the problem is ?
I have solved above problem from solution provided. Atually, I am generating notification as the datetime value from the databse matches to the current datetime value. but, it does not generating notification.
My code is as follows :
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
doAsynchTask = new TimerTask() {
#Override
public void run() {
Log.d("Timer Task Background", "Timer task background");
Calendar c = Calendar.getInstance();
c.setTime(new Date());
long time = System.currentTimeMillis();
Date dateCurrent = new Date(time);
Log.d(">>>>>>>Current Date : ", "" + dateCurrent);
getListData();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm a");
Date dateFromDatabase;
for (int i = 0; i < remiderList.size(); i++) {
try {
System.out.print("+++" + remiderList.get(i).toString());
dateFromDatabase = formatter.parse(remiderList.get(i).toString());
Log.d(">>>>>Database date : ", "" + dateFromDatabase);
if (dateCurrent.equals(dateFromDatabase)) {
Toast.makeText(getApplicationContext(), "Date matched", Toast.LENGTH_LONG).show();
displayNotification();
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}
};
timer.schedule(doAsynchTask, 0, 1000);
}
public void displayNotification() {
Notification.Builder builder = new Notification.Builder(MyRemiderService.this);
Intent intent1 = new Intent(this.getApplicationContext(),
HomeActivity.class);
Notification notification = new Notification(R.drawable.notification_template_icon_bg,
"This is a test message!", System.currentTimeMillis());
intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(
this.getApplicationContext(), 0, intent1,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setSmallIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha)
.setContentTitle("ContentTitle").setContentText("this for test massage")
.setContentIntent(pendingNotificationIntent);
notification = builder.getNotification();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
/* notification.setLatestEventInfo(this.getApplicationContext(),
"AlarmManagerDemo", "This is a test message!",
pendingNotificationIntent);*/
mManager.notify(0, notification);
}
#Override
public void onDestroy() {
super.onDestroy();
}
public void getListData() {
remiderList = dbHelper.getAllRemiders();
}
I have checked both the values in Logcat as follows :
09-15 17:50:00.629 17915-17927/? D/>>>>>>>Current Date :﹕ Tue Sep 15 17:50:00 GMT+05:30 2015
09-15 17:50:00.637 17915-17927/? D/>>>>>Database date :﹕ Tue Sep 15 17:50:00 GMT+05:30 2015
You have not set current date in calender object.
Calendar c = Calendar.getInstance();
c.setTime(new Date());
//Calendar.SECOND will return only seconds from the date
//int seconds = c.get(Calendar.SECOND);
long time = c.getTime();
Date date2 = new Date(time);
Log.d(">>>>>>>Current Date : ",""+date2);
You can use SimpleDateFormat class to format the dates as follow
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
System.out.println(format.format(new Date()));
try this
private String getCurrentDateAndTime() {
SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
return simple.format(new Date());
}
Avoid old date-time classes
You are using the old date-time classes bundled with the earliest versions of Java such as java.util.Date/.Calendar. They have proven to be poorly designed, confusing, and troublesome. Avoid them.
Among the many points of confusion is that a java.util.Date represents a calendar date and a time-of-day while a java.sql.Date pretends to represent only a date without any time-of-day although it does actually have a time-of-day just set to zeros (00:00:00.0).
java.time
The old date-time classes have been supplanted by the java.time framework. See Tutorial.
Java 8 and later: The java.time framework is built-in.
Java 7 & 6: Use the backport of java.time.
Android: Use this wrapped version of that backport.
java.sql
Eventually we should see JDBC drivers updated to deal with java.time types directly. Until then, we still need the java.sql types for getting data in/out of databases. But immediately call the new conversion methods added to the old classes to move into java.time types.
Instant
An Instant is a moment on the timeline in UTC with resolution up to nanoseconds.
java.sql.Timestamp ts = myResultSet.getTimestamp( x );
Instant instant = ts.toInstant();
LocalDate
If you are trying to compare the date-portion of that date time to today’s date, use the LocalDate class. This class truly represents a date-only value without time-of-day and without time zone.
Time Zone
Note that a time zone is crucial to determining dates, as the date may vary around the world by time zone for any given moment. So before extracting the LocalDate we need to apply a time zone (ZoneId) to get a ZonedDateTime. If you omit the time zone your JVM’s current default time zone is implicitly applied. Better to specify explicitly the desired/expected time zone.
ZoneId zoneId = ZoneId.of( "America/Montreal" ); // Or "Asia/Kolkata", "Europe/Paris", and so on.
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
LocalDate today = LocalDate.now( zoneId );
if( today.isEqual( zdt.toLocalDate() ) {
…
}
Notice that nowhere in that code did we use Strings; all date-time objects instead.
Formatting Strings
To generate a String as a textual representation of the date-time value, you can call the toString methods to get text formatted using the ISO 8601 standard. Or specify your own formatting pattern. Better yet, let java.time do the work of localizing automatically. Specify a Locale for a human language (English, French, etc.) to use in translating the name of day/month and such.
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM );
String output = zdt.format( formatter.withLocale( Locale.US ) ); // Or Locale.CANADA_FRENCH and so on.

How to set TimeZone in android for a particular date and time?

I developed an application , in that i need to save the the event date and time. By default the time and date are in "America/Chicago" timezone format. Now, i need to convert them into user's device Time Zone format. but i got wrong format.
I did the following.
SimpleDateFormat curFormater1=new SimpleDateFormat("MM-dd-yyyy-hh:mm a");//10-23-2012-08:30 am
curFormater1.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
curFormater1.setTimeZone(TimeZone.getDefault());
current output:
TimeZone.getTimeZone("America/Chicago") is 10-22-2012-10:00 PM
TimeZone.getDefault() is 10-23-2012-08:30 AM
Required output
TimeZone.getTimeZone("America/Chicago") is 10-23-2012-08:30 AM
TimeZone.getDefault() is 10-23-2012-07:00 PM
Had the same trouble but found a way out.
TimeZone sets to the device's timeZone by default. To change this and to set it to a specific timeZone use the getRawOffset() property.
This method calculates the milliseconds from the current time. So you can add the milliseconds for your specified timeZone and subtract those for the default timeZone.
When I tried to change it to timeZone 'GMT_ID'
values.put(CalendarContract.Events.DTSTART, startDate.getTime() +TimeZone.getTimeZone(GMT_ID).getRawOffset() -TimeZone.getDefault().getRawOffset());
Hope this helps.
Some examples
Convert time between timezone
Converting Times Between Time Zones
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
public class TimeZoneExample {
public static void main(String[] args) {
// Create a calendar object and set it time based on the local
// time zone
Calendar localTime = Calendar.getInstance();
localTime.set(Calendar.HOUR, 17);
localTime.set(Calendar.MINUTE, 15);
localTime.set(Calendar.SECOND, 20);
int hour = localTime.get(Calendar.HOUR);
int minute = localTime.get(Calendar.MINUTE);
int second = localTime.get(Calendar.SECOND);
// Print the local time
System.out.printf("Local time : %02d:%02d:%02d\n", hour, minute, second);
// Create a calendar object for representing a Germany time zone. Then we
// wet the time of the calendar with the value of the local time
Calendar germanyTime = new GregorianCalendar(TimeZone.getTimeZone("Germany"));
germanyTime.setTimeInMillis(localTime.getTimeInMillis());
hour = germanyTime.get(Calendar.HOUR);
minute = germanyTime.get(Calendar.MINUTE);
second = germanyTime.get(Calendar.SECOND);
// Print the local time in Germany time zone
System.out.printf("Germany time: %02d:%02d:%02d\n", hour, minute, second);
}
}

How to conert local time to UTC time in android [duplicate]

Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
When I create a new Date object, it is initialized to the current time but in the local timezone. How can I get the current date and time in GMT?
tl;dr
Instant.now() // Capture the current moment in UTC.
Generate a String to represent that value:
Instant.now().toString()
2016-09-13T23:30:52.123Z
Details
As the correct answer by Jon Skeet stated, a java.util.Date object has no time zone†. But its toString implementation applies the JVM’s default time zone when generating the String representation of that date-time value. Confusingly to the naïve programmer, a Date seems to have a time zone but does not.
The java.util.Date, j.u.Calendar, and java.text.SimpleDateFormat classes bundled with Java are notoriously troublesome. Avoid them. Instead, use either of these competent date-time libraries:
java.time.* package in Java 8
Joda-Time
java.time (Java 8)
Java 8 brings an excellent new java.time.* package to supplant the old java.util.Date/Calendar classes.
Getting current time in UTC/GMT is a simple one-liner…
Instant instant = Instant.now();
That Instant class is the basic building block in java.time, representing a moment on the timeline in UTC with a resolution of nanoseconds.
In Java 8, the current moment is captured with only up to milliseconds resolution. Java 9 brings a fresh implementation of Clock captures the current moment in up to the full nanosecond capability of this class, depending on the ability of your host computer’s clock hardware.
It’s toString method generates a String representation of its value using one specific ISO 8601 format. That format outputs zero, three, six or nine digits digits (milliseconds, microseconds, or nanoseconds) as necessary to represent the fraction-of-second.
If you want more flexible formatting, or other additional features, then apply an offset-from-UTC of zero, for UTC itself (ZoneOffset.UTC constant) to get a OffsetDateTime.
OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC );
Dump to console…
System.out.println( "now.toString(): " + now );
When run…
now.toString(): 2014-01-21T23:42:03.522Z
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.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - 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
Most 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 (<26), 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.
Joda-Time
UPDATE: The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
Using the Joda-Time 3rd-party open-source free-of-cost library, you can get the current date-time in just one line of code.
Joda-Time inspired the new java.time.* classes in Java 8, but has a different architecture. You may use Joda-Time in older versions of Java. Joda-Time continues to work in Java 8 and continues to be actively maintained (as of 2014). However, the Joda-Time team does advise migration to java.time.
System.out.println( "UTC/GMT date-time in ISO 8601 format: " + new org.joda.time.DateTime( org.joda.time.DateTimeZone.UTC ) );
More detailed example code (Joda-Time 2.3)…
org.joda.time.DateTime now = new org.joda.time.DateTime(); // Default time zone.
org.joda.time.DateTime zulu = now.toDateTime( org.joda.time.DateTimeZone.UTC );
Dump to console…
System.out.println( "Local time in ISO 8601 format: " + now );
System.out.println( "Same moment in UTC (Zulu): " + zulu );
When run…
Local time in ISO 8601 format: 2014-01-21T15:34:29.933-08:00
Same moment in UTC (Zulu): 2014-01-21T23:34:29.933Z
For more example code doing time zone work, see my answer to a similar question.
Time Zone
I recommend you always specify a time zone rather than relying implicitly on the JVM’s current default time zone (which can change at any moment!). Such reliance seems to be a common cause of confusion and bugs in date-time work.
When calling now() pass the desired/expected time zone to be assigned. Use the DateTimeZone class.
DateTimeZone zoneMontréal = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( zoneMontréal );
That class holds a constant for UTC time zone.
DateTime now = DateTime.now( DateTimeZone.UTC );
If you truly want to use the JVM’s current default time zone, make an explicit call so your code is self-documenting.
DateTimeZone zoneDefault = DateTimeZone.getDefault();
ISO 8601
Read about ISO 8601 formats. Both java.time and Joda-Time use that standard’s sensible formats as their defaults for both parsing and generating strings.
† Actually, java.util.Date does have a time zone, buried deep under layers of source code. For most practical purposes, that time zone is ignored. So, as shorthand, we say java.util.Date has no time zone. Furthermore, that buried time zone is not the one used by Date’s toString method; that method uses the JVM’s current default time zone. All the more reason to avoid this confusing class and stick with Joda-Time and java.time.
java.util.Date has no specific time zone, although its value is most commonly thought of in relation to UTC. What makes you think it's in local time?
To be precise: the value within a java.util.Date is the number of milliseconds since the Unix epoch, which occurred at midnight January 1st 1970, UTC. The same epoch could also be described in other time zones, but the traditional description is in terms of UTC. As it's a number of milliseconds since a fixed epoch, the value within java.util.Date is the same around the world at any particular instant, regardless of local time zone.
I suspect the problem is that you're displaying it via an instance of Calendar which uses the local timezone, or possibly using Date.toString() which also uses the local timezone, or a SimpleDateFormat instance, which, by default, also uses local timezone.
If this isn't the problem, please post some sample code.
I would, however, recommend that you use Joda-Time anyway, which offers a much clearer API.
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
//Local time zone
SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
//Time in GMT
return dateFormatLocal.parse( dateFormatGmt.format(new Date()) );
This definitely returns UTC time: as String and Date objects !
static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static Date getUTCdatetimeAsDate() {
// note: doesn't check for null
return stringDateToDate(getUTCdatetimeAsString());
}
public static String getUTCdatetimeAsString() {
final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
final String utcTime = sdf.format(new Date());
return utcTime;
}
public static Date stringDateToDate(String StrDate) {
Date dateToReturn = null;
SimpleDateFormat dateFormat = new SimpleDateFormat(DATEFORMAT);
try {
dateToReturn = (Date)dateFormat.parse(StrDate);
}
catch (ParseException e) {
e.printStackTrace();
}
return dateToReturn;
}
Calendar c = Calendar.getInstance();
System.out.println("current: "+c.getTime());
TimeZone z = c.getTimeZone();
int offset = z.getRawOffset();
if(z.inDaylightTime(new Date())){
offset = offset + z.getDSTSavings();
}
int offsetHrs = offset / 1000 / 60 / 60;
int offsetMins = offset / 1000 / 60 % 60;
System.out.println("offset: " + offsetHrs);
System.out.println("offset: " + offsetMins);
c.add(Calendar.HOUR_OF_DAY, (-offsetHrs));
c.add(Calendar.MINUTE, (-offsetMins));
System.out.println("GMT Time: "+c.getTime());
Actually not time, but it's representation could be changed.
SimpleDateFormat f = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(f.format(new Date()));
Time is the same in any point of the Earth, but our perception of time could be different depending on location.
This works for getting UTC milliseconds in Android.
Calendar c = Calendar.getInstance();
int utcOffset = c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET);
Long utcMilliseconds = c.getTimeInMillis() + utcOffset;
Calendar aGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
Then all operations performed using the aGMTCalendar object will be done with the GMT time zone and will not have the daylight savings time or fixed offsets applied
Wrong!
Calendar aGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
aGMTCalendar.getTime(); //or getTimeInMillis()
and
Calendar aNotGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT-2"));aNotGMTCalendar.getTime();
will return the same time. Idem for
new Date(); //it's not GMT.
This code prints the current time UTC.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class Test
{
public static void main(final String[] args) throws ParseException
{
final SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(f.format(new Date()));
}
}
Result
2013-10-26 14:37:48 UTC
Here is what seems to be incorrect in Jon Skeet's answer. He said:
java.util.Date is always in UTC. What makes you think it's in local
time? I suspect the problem is that you're displaying it via an
instance of Calendar which uses the local timezone, or possibly using
Date.toString() which also uses the local timezone.
However, the code:
System.out.println(new java.util.Date().getHours() + " hours");
gives the local hours, not GMT (UTC hours), using no Calendar and no SimpleDateFormat at all.
That is why is seems something is incorrect.
Putting together the responses, the code:
System.out.println(Calendar.getInstance(TimeZone.getTimeZone("GMT"))
.get(Calendar.HOUR_OF_DAY) + " Hours");
shows the GMT hours instead of the local hours -- note that getTime.getHours() is missing because that would create a Date() object, which theoretically stores the date in GMT, but gives back the hours in the local time zone.
If you want a Date object with fields adjusted for UTC you can do it like this with Joda Time:
import org.joda.time.DateTimeZone;
import java.util.Date;
...
Date local = new Date();
System.out.println("Local: " + local);
DateTimeZone zone = DateTimeZone.getDefault();
long utc = zone.convertLocalToUTC(local.getTime(), false);
System.out.println("UTC: " + new Date(utc));
You can use:
Calendar aGMTCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
Then all operations performed using the aGMTCalendar object will be done with the GMT time zone and will not have the daylight savings time or fixed offsets applied. I think the previous poster is correct that the Date() object always returns a GMT it's not until you go to do something with the date object that it gets converted to the local time zone.
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(date));
Here is my implementation of toUTC:
public static Date toUTC(Date date){
long datems = date.getTime();
long timezoneoffset = TimeZone.getDefault().getOffset(datems);
datems -= timezoneoffset;
return new Date(datems);
}
There's probably several ways to improve it, but it works for me.
You can directly use this
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("dd:MM:yyyy HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(dateFormatGmt.format(new Date())+"");
Here an other suggestion to get a GMT Timestamp object:
import java.sql.Timestamp;
import java.util.Calendar;
...
private static Timestamp getGMT() {
Calendar cal = Calendar.getInstance();
return new Timestamp(cal.getTimeInMillis()
-cal.get(Calendar.ZONE_OFFSET)
-cal.get(Calendar.DST_OFFSET));
}
Here is another way to get GMT time in String format
String DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z" ;
final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
String dateTimeString = sdf.format(new Date());
With:
Calendar cal = Calendar.getInstance();
Then cal have the current date and time.
You also could get the current Date and Time for timezone with:
Calendar cal2 = Calendar.getInstance(TimeZone.getTimeZone("GMT-2"));
You could ask cal.get(Calendar.DATE); or other Calendar constant about others details.
Date and Timestamp are deprecated in Java. Calendar class it isn't.
Sample code to render system time in a specific time zone and a specific format.
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class TimZoneTest {
public static void main (String[] args){
//<GMT><+/-><hour>:<minutes>
// Any screw up in this format, timezone defaults to GMT QUIETLY. So test your format a few times.
System.out.println(my_time_in("GMT-5:00", "MM/dd/yyyy HH:mm:ss") );
System.out.println(my_time_in("GMT+5:30", "'at' HH:mm a z 'on' MM/dd/yyyy"));
System.out.println("---------------------------------------------");
// Alternate format
System.out.println(my_time_in("America/Los_Angeles", "'at' HH:mm a z 'on' MM/dd/yyyy") );
System.out.println(my_time_in("America/Buenos_Aires", "'at' HH:mm a z 'on' MM/dd/yyyy") );
}
public static String my_time_in(String target_time_zone, String format){
TimeZone tz = TimeZone.getTimeZone(target_time_zone);
Date date = Calendar.getInstance().getTime();
SimpleDateFormat date_format_gmt = new SimpleDateFormat(format);
date_format_gmt.setTimeZone(tz);
return date_format_gmt.format(date);
}
}
Output
10/08/2011 21:07:21
at 07:37 AM GMT+05:30 on 10/09/2011
at 19:07 PM PDT on 10/08/2011
at 23:07 PM ART on 10/08/2011
Just to make this simpler, to create a Date in UTC you can use Calendar :
Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Which will construct a new instance for Calendar using the "UTC" TimeZone.
If you need a Date object from that calendar you could just use getTime().
Converting Current DateTime in UTC:
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
DateTimeZone dateTimeZone = DateTimeZone.getDefault(); //Default Time Zone
DateTime currDateTime = new DateTime(); //Current DateTime
long utcTime = dateTimeZone.convertLocalToUTC(currDateTime .getMillis(), false);
String currTime = formatter.print(utcTime); //UTC time converted to string from long in format of formatter
currDateTime = formatter.parseDateTime(currTime); //Converted to DateTime in UTC
public static void main(String args[]){
LocalDate date=LocalDate.now();
System.out.println("Current date = "+date);
}
This worked for me, returns the timestamp in GMT!
Date currDate;
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
long currTime = 0;
try {
currDate = dateFormatLocal.parse( dateFormatGmt.format(new Date()) );
currTime = currDate.getTime();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The Simple Function that you can use:
Edit: this version uses the modern java.time classes.
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("dd-MM-uuuu HH:mm:ss z");
public static String getUtcDateTime() {
return ZonedDateTime.now(ZoneId.of("Etc/UTC")).format(FORMATTER);
}
Return value from the method:
26-03-2022 17:38:55 UTC
Original function:
public String getUTC_DateTime() {
SimpleDateFormat dateTimeFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss z");
dateTimeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));//gmt
return dateTimeFormat.format(new Date());
}
return of above function:
26-03-2022 08:07:21 UTC
To put it simple. A calendar object stores information about time zone but when you perform cal.getTime() then the timezone information will be lost. So for Timezone conversions I will advice to use DateFormat classes...
this is my implementation:
public static String GetCurrentTimeStamp()
{
Calendar cal=Calendar.getInstance();
long offset = cal.getTimeZone().getOffset(System.currentTimeMillis());//if you want in UTC else remove it .
return new java.sql.Timestamp(System.currentTimeMillis()+offset).toString();
}
Use this Class to get ever the right UTC Time from a Online NTP Server:
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
class NTP_UTC_Time
{
private static final String TAG = "SntpClient";
private static final int RECEIVE_TIME_OFFSET = 32;
private static final int TRANSMIT_TIME_OFFSET = 40;
private static final int NTP_PACKET_SIZE = 48;
private static final int NTP_PORT = 123;
private static final int NTP_MODE_CLIENT = 3;
private static final int NTP_VERSION = 3;
// Number of seconds between Jan 1, 1900 and Jan 1, 1970
// 70 years plus 17 leap days
private static final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L;
private long mNtpTime;
public boolean requestTime(String host, int timeout) {
try {
DatagramSocket socket = new DatagramSocket();
socket.setSoTimeout(timeout);
InetAddress address = InetAddress.getByName(host);
byte[] buffer = new byte[NTP_PACKET_SIZE];
DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, NTP_PORT);
buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3);
writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET);
socket.send(request);
// read the response
DatagramPacket response = new DatagramPacket(buffer, buffer.length);
socket.receive(response);
socket.close();
mNtpTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET);
} catch (Exception e) {
// if (Config.LOGD) Log.d(TAG, "request time failed: " + e);
return false;
}
return true;
}
public long getNtpTime() {
return mNtpTime;
}
/**
* Reads an unsigned 32 bit big endian number from the given offset in the buffer.
*/
private long read32(byte[] buffer, int offset) {
byte b0 = buffer[offset];
byte b1 = buffer[offset+1];
byte b2 = buffer[offset+2];
byte b3 = buffer[offset+3];
// convert signed bytes to unsigned values
int i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0);
int i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1);
int i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2);
int i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3);
return ((long)i0 << 24) + ((long)i1 << 16) + ((long)i2 << 8) + (long)i3;
}
/**
* Reads the NTP time stamp at the given offset in the buffer and returns
* it as a system time (milliseconds since January 1, 1970).
*/
private long readTimeStamp(byte[] buffer, int offset) {
long seconds = read32(buffer, offset);
long fraction = read32(buffer, offset + 4);
return ((seconds - OFFSET_1900_TO_1970) * 1000) + ((fraction * 1000L) / 0x100000000L);
}
/**
* Writes 0 as NTP starttime stamp in the buffer. --> Then NTP returns Time OFFSET since 1900
*/
private void writeTimeStamp(byte[] buffer, int offset) {
int ofs = offset++;
for (int i=ofs;i<(ofs+8);i++)
buffer[i] = (byte)(0);
}
}
And use it with:
long now = 0;
NTP_UTC_Time client = new NTP_UTC_Time();
if (client.requestTime("pool.ntp.org", 2000)) {
now = client.getNtpTime();
}
If you need UTC Time "now" as DateTimeString use function:
private String get_UTC_Datetime_from_timestamp(long timeStamp){
try{
Calendar cal = Calendar.getInstance();
TimeZone tz = cal.getTimeZone();
int tzt = tz.getOffset(System.currentTimeMillis());
timeStamp -= tzt;
// DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.getDefault());
DateFormat sdf = new SimpleDateFormat();
Date netDate = (new Date(timeStamp));
return sdf.format(netDate);
}
catch(Exception ex){
return "";
}
}
and use it with:
String UTC_DateTime = get_UTC_Datetime_from_timestamp(now);
If you want to avoid parsing the date and just want a timestamp in GMT, you could use:
final Date gmt = new Timestamp(System.currentTimeMillis()
- Calendar.getInstance().getTimeZone()
.getOffset(System.currentTimeMillis()));
public class CurrentUtcDate
{
public static void main(String[] args) {
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("UTC Time is: " + dateFormat.format(date));
}
}
Output:
UTC Time is: 22-01-2018 13:14:35
You can change the date format as needed.
Current date in the UTC
Instant.now().toString().replaceAll("T.*", "");

Categories

Resources