1 hour time difference daylight saving time issue - java

Function to convert server date to device local time:
public static String convertIntoLocalTime(String strTime, String whichTimeZone, String dateFormat) {
String strLocalTime = null;
try {
SimpleDateFormat sdf = getSimpleDateFormat(dateFormat, whichTimeZone);
Date date = sdf.parse(strTime);
AppLog.e(TAG,"Timezone = " + whichTimeZone);
AppLog.e(TAG,"Date = " + strTime);
AppLog.e(TAG,"Date in CET = " + date.toString());
AppLog.e(TAG,"inDaylightTime = " + sdf.getTimeZone().inDaylightTime(date));
AppLog.e(TAG,"DST savings = " + sdf.getTimeZone().getDSTSavings());
if (sdf.getTimeZone().getDSTSavings() == 3600000) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.HOUR, 1);
Date oneHourBack = cal.getTime();
SimpleDateFormat local = getLocalSimpleDateFormat(dateFormat);
strLocalTime = local.format(oneHourBack);
} else {
SimpleDateFormat local = getLocalSimpleDateFormat(dateFormat);
strLocalTime = local.format(date);
}
} catch (ParseException e) {
AppLog.e(TAG, e.getMessage(), e);
}
AppLog.e(TAG,"Local Time = " + strLocalTime);
return strLocalTime;
}
Function to get simple date format:
private static SimpleDateFormat getSimpleDateFormat(String format, String tz) {
TimeZone timeZone = TimeZone.getTimeZone(tz);
timeZone.useDaylightTime();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format, Locale.getDefault());
simpleDateFormat.setTimeZone(timeZone);
return simpleDateFormat;
}
Function to get simple date format for local device conversion:
/**
* #param format
* #return
*/
private static SimpleDateFormat getLocalSimpleDateFormat(String format) {
TimeZone timeZone = TimeZone.getDefault();
timeZone.useDaylightTime();
SimpleDateFormat localSdf = new SimpleDateFormat(format, Locale.getDefault());
localSdf.setTimeZone(timeZone);
return localSdf;
}
Output:
Date = 2018-04-22 14:30
Date in CET = Sun Apr 22 13:30:00 GMT+01:00 2018
inDaylightTime = true
DST savings = 3600000
Local Time = 2018-04-22 14:30
The above code was working perfectly fine earlier, for example we have 1 event on 1st of April where it was showing time correctly but at the moment starting from 21 April its showing additional 1 hour time.
I have tried to convert the date coming from server using UTC as well as CET but in both the cases its showing me additional one hour when converting it to device local time.
The above example is based on London timezone, whereas when we tried it in IST timezone it was returning the correct time.
We have handled DST time different by checking inDaylightTime function of timezone but it's not working.
I am sure that there is something related to DST but I am not able to figure it out. Thanks for your help?

First, you are using the old and long outdated date and time classes: SimpleDateFormat, Date, Calendar and TimeZone. These are renowned for being poorly designed and sometimes troublesome to work with. My first suggestion is you rewrite your code using java.time, the modern Java date and time API. It is much less buggy, and I expect that you will more easily develop correct code.
That said, no matter if you use the old-fashioned or the modern classes, don’t handle summer time yourself. The library classes will do it for you. Your job is to get the time zones correct. Don’t add or subtract an hour to compensate for summer time. Look at other questions about converting from one time zone to another, there are many.
Don’t use three and four letter time zone abbreviations. CET is not a time zone. IST is ambiguous, it may mean Irish Summer Time, Israel Standard Time or India Standard Time. The countries in Europe that use CET in winter have used CEST (Central European Summer Time) since March 26, 2018.
Instead give server time zone as continent/city such as Europe/London if this is the server time zone. It’s unambiguous.
Also make sure to set your device time zone to a true time zone. It seems you’ve got it set to GMT+01:00, which is a GMT offset, not a time zone. It agrees with Europe/London time zone and with CET in winter, but not after March 26.
Finally, you are adding 1 hour to your Calendar, turning it 1 hour forward, and then calling the Date you get from it oneHourBack. This looks wrong. Did you mean to subtract 1 hour, or did you mean that the variable should be oneHourForward?
EDIT: I probably haven’t understood exactly which time zones are the correct ones for you, and therefore not what would be the correct output for your code. So take the following only as a guess at what you were trying to accomplish. And please fill in the correct time zones.
public static String convertIntoLocalTime(
String strTime, String serverTimeZone, String dateFormat) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat);
ZonedDateTime serverDateTime = LocalDateTime.parse(strTime, formatter)
.atZone(ZoneId.of(serverTimeZone));
AppLog.e(TAG, "Server timezone = " + serverTimeZone);
AppLog.e(TAG, "Date = " + strTime);
AppLog.e(TAG, "Date in server timezone = " + serverDateTime.toString());
ZonedDateTime deviceTime = serverDateTime
.withZoneSameInstant(ZoneId.systemDefault());
String strLocalTime = deviceTime.format(formatter);
AppLog.e(TAG, "Device Time = " + deviceTime);
AppLog.e(TAG, "Local Time = " + strLocalTime);
return strLocalTime;
}
I tried setting my time zone to Europe/London and issuing the following call:
convertIntoLocalTime("2018-04-22 14:30", "Europe/Berlin", "yyyy-MM-dd HH:mm")
The output I got was:
Server timezone = Europe/Berlin
Date = 2018-04-22 14:30
Date in server timezone = 2018-04-22T14:30+02:00[Europe/Berlin]
Device Time = 2018-04-22T13:30+01:00[Europe/London]
Local Time = 2018-04-22 13:30
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26, I’m told) 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.
Links
List of tz database time zones
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.

I was not tested so try it first.
public String convertIntoLocalTime(String strTime, String whichTimeZone, String dateFormat) {
String strLocalTime = null;
strLocalTime=convertDateToUserTimeZone(strTime,whichTimeZone,dateFormat);
return strLocalTime;
}
public String convertDateToUserTimeZone(String strTime, String whichTimeZone, String dateFormat) {
String ourdate;
try {
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat, Locale.UK);
formatter.setTimeZone(TimeZone.getTimeZone(whichTimeZone));
Date value = formatter.parse(strTime);
TimeZone timeZone = TimeZone.getTimeZone("Asia/Kolkata");
SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat, Locale.UK); //this format changeable
dateFormatter.setTimeZone(timeZone);
ourdate = dateFormatter.format(value);
//Log.d("OurDate", OurDate);
} catch (Exception e) {
ourdate = "00-00-0000 00:00";
}
return ourdate;
}

Related

Java and converting displayed value into local time zone and daylight savings

I know this is an oft asked type of question, and I've been looking around the web for solutions, but to no avail. The problem is that we're fetching a date value from the database and want to display it in a PDF in local time. The raw formatted value is "2022/05/24 15:18:10" and using Costa Rica as an example client time zone (we're in LA), we'd want this "2022/05/24 16:18:10". However, we're getting this: "2022/05/24 17:18:10".
One of the odd things I'm seeing when I run the code below is that it seems that our server time zone is PST, according to Java, but is actually PDT.
creationDate from db=Tue May 24 15:18:10 PDT 2022
Desired creationDate output=2022/05/24 16:18:10
cal.getTimeZone.getDisplayName()=Pacific Standard Time
formatted creationDate=2022/05/24 17:18:10
So one question is: why are we seeing PST instead of PDT and the second question is how do I fix this?
Example code:
public static void main(
String[] args)
{
final String DATE_TIME_PATTERN = "yyyy/MM/dd HH:mm:ss";
final String LA_TIMEZONE_ID = "America/Los_Angeles";
DateFormat df = new SimpleDateFormat(DATE_TIME_PATTERN);
TimeZone serverTimeZone = TimeZone.getTimeZone(LA_TIMEZONE_ID);
Calendar cal = Calendar.getInstance(/* serverTimeZone */); // works same with or without param
TimeZone clientTimeZone = TimeZone.getTimeZone("CST"); // Costa Rica = Central Standard Time
Date creationDate;
df.setTimeZone(clientTimeZone);
// Values as fetched from database.
cal.set(Calendar.DAY_OF_MONTH, 24);
cal.set(Calendar.MONTH, Calendar.MAY);
cal.set(Calendar.YEAR, 2022);
cal.set(Calendar.HOUR_OF_DAY, 15);
cal.set(Calendar.MINUTE, 18);
cal.set(Calendar.SECOND, 10);
creationDate = cal.getTime();
System.out.println("creationDate from db=" + creationDate.toString());
System.out.println("Desired creationDate output=2022/05/24 16:18:10");
System.out.println("cal.getTimeZone.getDisplayName()=" + cal.getTimeZone().getDisplayName());
System.out.println("formatted creationDate=" + df.format(creationDate));
}
So, after a bit of hacking and googling, it would appear (at least to me), that "Central Standard Time" isn't what you want to use (nor should you use it generally).
From time-and-date/Central Standard Time (CST)
Caution: This is NOT the current local time in most locations in that time zone
North America: Only some locations are currently on CST because most places in this time zone are currently on summer time / daylight saving time and are observing CDT.
And then add in time-and-date/Time Zone in Costa Rica
Costa Rica observes Central Standard Time all year. There are no Daylight Saving Time clock changes.
That's not confusing at all 🙄. So, as I "understand" it, CST is normally -6 hours and CDT is -5 hours, but Costa Rica is always -6 hours.
So, based on the observations of your code, CST seems to be having the day light savings value applied to it, regardless of what you do.
So, what to do about it? Well, the simple answer is, don't use it, in fact, stop using the java.util.Date and related APIs altogether and instead, make use of the replacement java.time APIS and the America/Costa_Rica time zone directly, for example...
final String DATE_TIME_PATTERN = "yyyy/MM/dd HH:mm:ss";
final String LA_TIMEZONE_ID = "America/Los_Angeles";
final String dateStringValue = "2022/05/24 15:18:10";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime ldt = LocalDateTime.parse(dateStringValue, formatter);
ZoneId zoneId = ZoneId.of(LA_TIMEZONE_ID);
ZonedDateTime zdt = ldt.atZone(zoneId);
System.out.println(" Local = " + ldt);
System.out.println(" zdt = " + zdt);
System.out.println("Costa_Rica = " + zdt.withZoneSameInstant(ZoneId.of("America/Costa_Rica")));
System.out.println("US/Central = " + zdt.withZoneSameInstant(ZoneId.of("US/Central")));
which prints...
Local = 2022-05-24T15:18:10
zdt = 2022-05-24T15:18:10-07:00[America/Los_Angeles]
Costa_Rica = 2022-05-24T16:18:10-06:00[America/Costa_Rica]
US/Central = 2022-05-24T17:18:10-05:00[US/Central]
This is probably also a good (and over due) reason to dump the old java.util.Date and related classes and update to the java.time APIs, see the date/time trail for more details
Handling Daylight Savings Time in Java might also be worth a read

Changing the date format for a date range programmatically

I have an application where I want to change the date format in 'From' and 'To'.
Lets assume, I have a date range like 2018-06-11 - 2018-06-14. Now, I want to change it in some other format as 11 June, 2018 - 14 June, 2018.
Please refer the code below, I have tried:
String strDate = "2018-06-11 - 2018-06-14";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
try {
Date date = format.parse(strDate);
format = new SimpleDateFormat("dd MMMM, yyyy");
String strFinalDate = format.format(date);
tv4.setText(strFinalDate);
} catch (ParseException e) {
e.printStackTrace();
}
Also, I tried the below code as well:
String strDate = "2018-06-11 - 2018-06-14";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd - yyyy-MM-dd");
try {
Date date = format.parse(strDate);
format = new SimpleDateFormat("dd MMMM, yyyy - dd MMMM, yyyy");
String strFinalDate = format.format(date);
tv4.setText(strFinalDate);
} catch (ParseException e) {
e.printStackTrace();
}
First, set of code runs smoothly, but converts only the 'From' and doesn't even checks for 'To' date.
And, second set of code returns an error which says, java.text.ParseException: Unparseable date: "2017-01-11 - 2017-01-14
Have I skipped anything in this code?
Please notify me if I have.
Thanks!
I suggest
DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG);
String strDate = "2018-06-11 - 2018-06-14";
String[] strDates = strDate.split(" - ");
if (strDates.length != 2) {
throw new IllegalStateException("Wrong range format " + strDate
+ ", must be yyyy-MM-dd - yyyy-MM-dd");
}
String strFinalDate = LocalDate.parse(strDates[0]).format(dateFormatter)
+ " - " + LocalDate.parse(strDates[1]).format(dateFormatter);
System.out.println(strFinalDate);
Output on my Java with US English locale:
11 June 2018 - 14 June 2018
You don’t get the comma after “June” because this is not considered standard, so consider if this isn’t really an advantage. The output will depend on locale setting, which may be an advantage too. Or specify explicit locale for example:
DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)
.withLocale(Locale.UK);
I am using and recommending java.time, the modern Java date and time API.
What went wrong in your code?
No matter if you use an old-fashiuoned Date or a modern LocalDate, such an object can only hold one date, not a date range. In your first attempt SimpleDateFormat parsed the first date (since it matched your pattern) and then ignored the remainder of the string. So when you formatted the parsed date, you got
11 June, 2018
In your seconds attempt both dates were parsed, but into the same Date object, so only the values of the second date were kept. When printing the date its values were also printed twice since the format pattern for formatting contains the format twice:
14 June, 2018 - 14 June, 2018
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26, I’m told) 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.
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.
As I stated in my comment above, you have to split your strDate String into two different String variables. Have a look at the code below
String strDate = "2018-06-11 - 2018-06-14";
String[] fromToDatesStr = strDate.split(" - ");
String fromDateStr = fromToDatesStr[0];
String toDateStr = fromToDatesStr[1];
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date fromDate = null;
Date toDate = null;
try {
fromDate = format.parse(fromDateStr);
toDate = format.parse(toDateStr);
format = new SimpleDateFormat("dd MMMM, yyyy");
String strFromFinalDate = format.format(fromDate);
String strToFinalDate = format.format(toDate);
} catch (ParseException e) {
e.printStackTrace();
}
String strFromFinalDate and String strToFinalDate now contain the dates formatted as you desire.

Convert input String date time from different timezone to UTC

My system located in Singapore (timezone - "Asia/Singapore") receives a String datetime (yyyy-MM-dd HH:mm:ss) from a external system in Indonesia (timezone - "Asia/Jarkata").
How do I convert the received String datetime to UTC in java 1.7?
This is my code:
public void convertToUtc() {
String inputTime = "2018-02-02 10:09:00";
TimeZone inputTz = TimeZone.getTimeZone("Asia/Jarkarta");
TimeZone utcTz = TimeZone.getTimeZone("UTC");
SimpleDateFormat inputSdf = new SimpleDateFormat(DateTimeUtils.DATE_TIME_FORMAT);
inputSdf.setTimeZone(inputTz);
SimpleDateFormat utcSdf = new SimpleDateFormat(DateTimeUtils.ISO_DATE_TIME_FORMAT);
utcSdf.setTimeZone(utcTz);
// From time
Date fromDate = null;
try {
fromDate = inputSdf.parse(inputTime);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Convert to UTC
String sUtcDateTime = utcSdf.format(fromDate);
System.out.println("UTC: " + sUtcDateTime); // UTC: 2018-02-02T10:09:00.000Z. Expected 2018-02-02T03:09:00.000Z
}
janith1024’s answer is correct. However, I believe the real problem is that the old (and long outdated) TimeZone class behaves badly and doesn’t inform you of your spelling mistake. After all, we could all make that. So the real solution is to use java.time, the modern Java date and time API. On Java 7 (and 6) add ThreeTen Backport to your project, import:
import org.threeten.bp.ZoneId;
And then:
ZoneId inputTz = ZoneId.of("Asia/Jarkarta");
This gives you a org.threeten.bp.zone.ZoneRulesException: Unknown time-zone ID: Asia/Jarkarta. I should say that this greatly increases your chance of discovering your spelling error (the correct spelling is Asia/Jakarta).
The documentation of TimeZone.getTimeZone() says that it returns
the specified TimeZone, or the GMT zone if the given ID cannot be
understood.
However I am posting this answer because your issue is not just a lone example. Over and over we see questions on Stack Overflow coming from the old date and time classes showing surprising behaviour and in particular not detecting problems with the data we pass to them that it’s easy to detect. I very warmly recommend using the modern API instead.
In Java 8 and later, java.time is built-in, and you should import your date and time classes from java.time with subpackages rather than from org.threeten.bp.
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.
I check your code there was a spelling mistake in time zone so I correct it
public static void convertToUtc() {
String inputTime = "2018-02-02 10:09:00";
TimeZone inputTz = TimeZone.getTimeZone("Asia/Jakarta");
TimeZone utcTz = TimeZone.getTimeZone("UTC");
SimpleDateFormat inputSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
inputSdf.setTimeZone(inputTz);
SimpleDateFormat utcSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
utcSdf.setTimeZone(utcTz);
// From time
Date fromDate = null;
try {
fromDate = inputSdf.parse(inputTime);
}
catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Convert to UTC
String sUtcDateTime = utcSdf.format(fromDate);
System.out.println("UTC: " + sUtcDateTime); // print this UTC: 2018-02-02 03:09:00.
}

After parsing date string into Date and the converting it to millis, the output time is always lower on two hours

I am trying to parse a String with a date into a Date object and then convert it into millis.
But whatever I am doing - the output result in millis is always lower in 2 hours than the input date.
For example if the input date is 2018-1-10 11:30 - the output date will be 2018-01-10 9:30.
This is my code:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String dateString = "2018-1-10 11:30";
Date resultDate = sdf.parse(dateString);
long millis = resultDate.getTime();
// millis = 1515576600000
// When i am trying to convert millis to normal date via online
// converters i am always getting
// this result 10.01.18 9:30
I cannot understand why this is happening. How can I get back valid result after converting millis back? Why I got this difference in two hours?
It looks like a timezone problem.
Check in which timezone you are. If you are in UTC +02:00 the result is good !
If you want to set manually the timezone to match with UTC (without offset), check this stack overflow question: How to set time zone of a java.util.Date?
I hope this help you :)
One more example of where java.time, the modern Java date and time API, excels. It forces you to specify zone offset or time zone for operations like this one, which solves the problem:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-M-d H:mm");
String dateString = "2018-1-10 11:30";
long epochMillis = LocalDateTime.parse(dateString, dtf)
.atOffset(ZoneOffset.UTC)
.toInstant()
.toEpochMilli();
The result is 1515583800000 (maybe more readable as 1 515 583 800 000). Remove the last three zeros to convert to seconds and enter them on, for example, http://www.onlineconversion.com/unix_time.htm. The result is:
Wed, 10 Jan 2018 11:30:00 GMT
The GMT in the end confirms that the time is at the expected offset (for now we can consider GMT and UTC equivalent).
Question: Can I use java.time on Android?
You certainly can (I haven’t got the experience myself, though).
For the general Android market, use the Android edition of ThreeTen Backport (mentioned below). It’s called ThreeTenABP. Then import org.threeten.bp.format.DateTimeFormatter and org.threeten.bp.LocalDateTime.
For a newer Android device with Java 8 it should work out-of-the-box if you import java.time.format.DateTimeFormatter and java.time.LocalDateTime.
And on non-Android Java?
In Java 8 and later the new API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310).
Links
Oracle tutorial: Date Time, explaining how to use java.time.
ThreeTen Backport project
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Java Specification Request (JSR) 310, where the modern date and time API was first described.
By parsing the string it is assumed that the given time is based on your local time, whereas Date is in UTC. SimpleDateFormat does the conversion for you using your pcs time zone if you don't specify it.
https://docs.oracle.com/javase/7/docs/api/java/text/DateFormat.html#setTimeZone(java.util.TimeZone)
https://docs.oracle.com/javase/8/docs/api/java/util/Date.html
To convert it back you should use new Date (millis)
This considers your timezone as well and your result should be correct.
I think you are aware now that it is a timezone issue, but I figured I'll supply you a helper class that I wrote and use in most my applications as client server applications always have to take in account timezones and should be storing GMT on the server.
Hope this helps, you can copy and paste this class and handle a lot of your date formatting and timezone issues to and from the server.
public class DateHelper {
/*///////////////////////////////////////////////////////////////
// MEMBERS
*////////////////////////////////////////////////////////////////
public static SimpleDateFormat MY_APPS_CUSTOM_FORMATTER;
public final static String MMMM_dd = "MMMM, dd";
public final static String MMM_dd_yyyy = "MMM dd yyyy";
public final static String MMSlashddSlashyy = "MM/dd/yy";
public final static String MMSlashddSlashyy_hhColonmm_a = "MM/dd/yy hh:mm a";
public final static Calendar mCalender = Calendar.getInstance();
public final static TimeZone mLocalTimezone = mCalender.getTimeZone();
/*///////////////////////////////////////////////////////////////
// PROPERTIES
*////////////////////////////////////////////////////////////////
public synchronized static SimpleDateFormat getMyAppsDateCustomFormatter(boolean toServer, String format){
MY_APPS_CUSTOM_FORMATTER = new SimpleDateFormat(format);
if(toServer){
MY_APPS_CUSTOM_FORMATTER.setTimeZone(TimeZone.getTimeZone("UTC"));
}else{
MY_APPS_CUSTOM_FORMATTER.setTimeZone(mLocalTimezone);
}
return MY_APPS_CUSTOM_FORMATTER;
}
/*///////////////////////////////////////////////////////////////
// EXTRA HELPER METHODS
*////////////////////////////////////////////////////////////////
public static String getNowLocalTime(String formatToReturn){
return getMyAppsDateCustomFormatter(false, formatToReturn).format(new Date());
}
/*///////////////////////////////////////////////////////////////
// FROM SERVER FORMATTING
*////////////////////////////////////////////////////////////////
public static String getLocalDateStringFromGMTLong(long gmtTimestamp, String formatToReturn){
return getMyAppsDateCustomFormatter(false, formatToReturn).format(new Date(gmtTimestamp * 1000));
}
public static Date getDateFromLocalFormattedString(String date, String formatToUse, boolean toServer) throws Exception{
Date parsedDate = null;
try {
parsedDate = getMyAppsDateCustomFormatter(toServer, formatToUse).parse(date);
} catch (ParseException e) { //developer error, do NOT localize
throw new Exception(Globals.DEV_ERROR_STRINGS.INVALID_DATE_SUPPLIED_FOR_DEFAULT_FORMATTER);
}
return parsedDate;
}
public static String getFormattedStringFromLocalDate(Date date, String formatToUse) throws Exception{
return getMyAppsDateCustomFormatter(false, formatToUse).format(date);
}
/*///////////////////////////////////////////////////////////////
// TO SERVER FORMATTING
*////////////////////////////////////////////////////////////////
public static long getGMTLongFromLocalDate(Date date){
//Get Local Timezone
TimeZone tz = TimeZone.getDefault();
//Create new date for offset to GMT
Date ret = new Date(date.getTime() - tz.getRawOffset() );
// if we are now in DST, back off by the delta. Note that we are checking the GMT date, this is the KEY.
if ( tz.inDaylightTime( ret )){
Date dstDate = new Date( ret.getTime() - tz.getDSTSavings() );
// check to make sure we have not crossed back into standard time
// this happens when we are on the cusp of DST (7pm the day before the change for PDT)
if ( tz.inDaylightTime( dstDate )){
ret = dstDate;
}
}
return ret.getTime();
}
public static long getGMTLongFromLocalDateString(String date, String formatUsed) throws Exception {
Date passedDate = getDateFromLocalFormattedString(date, formatUsed, true);
//Get Local Timezone
TimeZone tz = TimeZone.getDefault();
//Create new date for offset to GMT
Date ret = new Date(passedDate.getTime() - tz.getRawOffset() );
// if we are now in DST, back off by the delta. Note that we are checking the GMT date, this is the KEY.
if ( tz.inDaylightTime( ret )){
Date dstDate = new Date( ret.getTime() - tz.getDSTSavings() );
// check to make sure we have not crossed back into standard time
// this happens when we are on the cusp of DST (7pm the day before the change for PDT)
if ( tz.inDaylightTime( dstDate )){
ret = dstDate;
}
}
return ret.getTime() / 1000;
}
public static long getNowGMTTime(){
return getGMTLongFromLocalDate(new Date());
}
}

Why is the month changed to 50 after I added 10 minutes?

I have this date object:
SimpleDateFormat df = new SimpleDateFormat("yyyy-mm-dd HH:mm");
Date d1 = df.parse(interviewList.get(37).getTime());
value of d1 is Fri Jan 07 17:40:00 PKT 2011
Now I am trying to add 10 minutes to the date above.
Calendar cal = Calendar.getInstance();
cal.setTime(d1);
cal.add(Calendar.MINUTE, 10);
String newTime = df.format(cal.getTime());
Value of newTime changes to 2011-50-07 17:50
but it should be 07-01-2011 17:50.
It adds minutes correctly but it also changes month, don't know why!
The issue for you is that you are using mm. You should use MM. MM is for month and mm is for minutes. Try with yyyy-MM-dd HH:mm
Other approach:
It can be as simple as this (other option is to use joda-time)
static final long ONE_MINUTE_IN_MILLIS=60000;//millisecs
Calendar date = Calendar.getInstance();
long t= date.getTimeInMillis();
Date afterAddingTenMins=new Date(t + (10 * ONE_MINUTE_IN_MILLIS));
you can use DateUtils class in org.apache.commons.lang3.time package
int addMinuteTime = 5;
Date targetTime = new Date(); //now
targetTime = DateUtils.addMinutes(targetTime, addMinuteTime); //add minute
Convenience method for implementing #Pangea's answer:
/*
* Convenience method to add a specified number of minutes to a Date object
* From: http://stackoverflow.com/questions/9043981/how-to-add-minutes-to-my-date
* #param minutes The number of minutes to add
* #param beforeTime The time that will have minutes added to it
* #return A date object with the specified number of minutes added to it
*/
private static Date addMinutesToDate(int minutes, Date beforeTime){
final long ONE_MINUTE_IN_MILLIS = 60000;//millisecs
long curTimeInMs = beforeTime.getTime();
Date afterAddingMins = new Date(curTimeInMs + (minutes * ONE_MINUTE_IN_MILLIS));
return afterAddingMins;
}
In order to avoid any dependency you can use java.util.Calendar as follow:
Calendar now = Calendar.getInstance();
now.add(Calendar.MINUTE, 10);
Date teenMinutesFromNow = now.getTime();
In Java 8 we have new API:
LocalDateTime dateTime = LocalDateTime.now().plus(Duration.of(10, ChronoUnit.MINUTES));
Date tmfn = Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
This is incorrectly specified:
SimpleDateFormat df = new SimpleDateFormat("yyyy-mm-dd HH:mm");
You're using minutes instead of month (MM)
tl;dr
LocalDateTime.parse(
"2016-01-23 12:34".replace( " " , "T" )
)
.atZone( ZoneId.of( "Asia/Karachi" ) )
.plusMinutes( 10 )
java.time
Use the excellent java.time classes for date-time work. These classes supplant the troublesome old date-time classes such as java.util.Date and java.util.Calendar.
ISO 8601
The java.time classes use standard ISO 8601 formats by default for parsing/generating strings of date-time values. To make your input string comply, replace the SPACE in the middle with a T.
String input = "2016-01-23 12:34" ;
String inputModified = input.replace( " " , "T" );
LocalDateTime
Parse your input string as a LocalDateTime as it lacks any info about time zone or offset-from-UTC.
LocalDateTime ldt = LocalDateTime.parse( inputModified );
Add ten minutes.
LocalDateTime ldtLater = ldt.plusMinutes( 10 );
ldt.toString(): 2016-01-23T12:34
ldtLater.toString(): 2016-01-23T12:44
See live code in IdeOne.com.
That LocalDateTime has no time zone, so it does not represent a point on the timeline. Apply a time zone to translate to an actual moment. Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland, or Asia/Karachi. Never use the 3-4 letter abbreviation such as EST or IST or PKT as they are not true time zones, not standardized, and not even unique(!).
ZonedDateTime
If you know the intended time zone for this value, apply a ZoneId to get a ZonedDateTime.
ZoneId z = ZoneId.of( "Asia/Karachi" );
ZonedDateTime zdt = ldt.atZone( z );
zdt.toString(): 2016-01-23T12:44+05:00[Asia/Karachi]
Anomalies
Think about whether to add those ten minutes before or after adding a time zone. You may get a very different result because of anomalies such as Daylight Saving Time (DST) that shift the wall-clock time.
Whether you should add the 10 minutes before or after adding the zone depends on the meaning of your business scenario and rules.
Tip: When you intend a specific moment on the timeline, always keep the time zone information. Do not lose that info, as done with your input data. Is the value 12:34 meant to be noon in Pakistan or noon in France or noon in Québec? If you meant noon in Pakistan, say so by including at least the offset-from-UTC (+05:00), and better still, the name of the time zone (Asia/Karachi).
Instant
If you want the same moment as seen through the lens of UTC, extract an Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = zdt.toInstant();
Convert
Avoid the troublesome old date-time classes whenever possible. But if you must, you can convert. Call new methods added to the old classes.
java.util.Date utilDate = java.util.Date.from( instant );
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 java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and 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 SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
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.
There's an error in the pattern of your SimpleDateFormat. it should be
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
use this format,
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
mm for minutes and MM for mounth
Once you have you date parsed, I use this utility function to add hours, minutes or seconds:
public class DateTimeUtils {
private static final long ONE_HOUR_IN_MS = 3600000;
private static final long ONE_MIN_IN_MS = 60000;
private static final long ONE_SEC_IN_MS = 1000;
public static Date sumTimeToDate(Date date, int hours, int mins, int secs) {
long hoursToAddInMs = hours * ONE_HOUR_IN_MS;
long minsToAddInMs = mins * ONE_MIN_IN_MS;
long secsToAddInMs = secs * ONE_SEC_IN_MS;
return new Date(date.getTime() + hoursToAddInMs + minsToAddInMs + secsToAddInMs);
}
}
Be careful when adding long periods of time, 1 day is not always 24 hours (daylight savings-type adjustments, leap seconds and so on), Calendar is recommended for that.
Can be done without the constants (like 3600000 ms is 1h)
public static Date addMinutesToDate(Date date, int minutes) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.MINUTE, minutes);
return calendar.getTime();
}
public static Date addHoursToDate(Date date, int hours) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.HOUR_OF_DAY, hours);
return calendar.getTime();
}
example of usage:
System.out.println(new Date());
System.out.println(addMinutesToDate(new Date(), 5));
Tue May 26 16:16:14 CEST 2020
Tue May 26 16:21:14 CEST 2020
Work for me DateUtils
//import
import org.apache.commons.lang.time.DateUtils
...
//Added and removed minutes to increase current range dates
Date horaInicialCorteEspecial = DateUtils.addMinutes(new Date(corteEspecial.horaInicial.getTime()),-1)
Date horaFinalCorteEspecial = DateUtils.addMinutes(new Date(corteEspecial.horaFinal.getTime()),1)
For android developers, here's a kotlin implementation using an extension of #jeznag's answer
fun Date.addMinutesToDate(minutes: Int): Date {
val minuteMillis: Long = 60000 //millisecs
val curTimeInMs: Long = this.time
val result = Date(curTimeInMs + minutes * minuteMillis)
this.time = result.time
return this
}
an unit test to check functionality works as expected
#Test
fun `test minutes are added to date`() {
//given
val date = SimpleDateFormat("dd-MM-yyyy hh:mm").parse("29-04-2021 23:00")
//when
date?.addMinutesToDate(45)
//then
val calendar = Calendar.getInstance()
calendar.time = date
assertEquals(29, calendar[Calendar.DAY_OF_MONTH])
assertEquals(23, calendar[Calendar.HOUR_OF_DAY])
assertEquals(45, calendar[Calendar.MINUTE])
}
Just for anybody who is interested. I was working on an iOS project that required similar functionality so I ended porting the answer by #jeznag to swift
private func addMinutesToDate(minutes: Int, beforeDate: NSDate) -> NSDate {
var SIXTY_SECONDS = 60
var m = (Double) (minutes * SIXTY_SECONDS)
var c = beforeDate.timeIntervalSince1970 + m
var newDate = NSDate(timeIntervalSince1970: c)
return newDate
}

Categories