3

I am able to convert date to days using the below code.

 SimpleDateFormat sfd = new SimpleDateFormat("yyyy-MM-dd");
 String s1 = sfd.format(dateObj);
 String a1 [] = s1.split("-");
 int year = Integer.parseInt(a1[0].toString());
 int month = Integer.parseInt(a1[1])-1;
 int day = Integer.parseInt((a1[2]));

 Calendar c1 = Calendar.getInstance();
 c1.set(year,month,day);

 days = c1.getTime().getTime()/(24*60*60*1000);

The above code works accurately in my system which is windows with timezone GMT +5.30.

However the same code in EST or Pacific timezone adds a day by 1 to final result when the time is 20.00 in the system.

What could be the issue ?

Do we need to set Timezone explicitly in the code ?

input dates does not hold any time stamp .. is it correct to store in java.util.Date instead of java.sql.Date?

Prince John Wesley
  • 62,492
  • 12
  • 87
  • 94
GKD
  • 53
  • 1
  • 1
  • 7
  • Do you want to get the count of days since 1/1/1970 ignoring the timezone or respecting the timezone? – micfra Oct 31 '11 at 11:33

2 Answers2

4

EDIT: As per Alex's comment, it's possible that the problems with the start of your code have blinded me to your real aim.

A Date represents an instant in time. That can fall on different dates depending on the time zone, but how do you want that to affect things? Do you want the number of days since the Unix epoch (which is always UTC) or the number of days since the 1st January 1970 in a particular time zone? Why do you want this "number of days" instead of a representation of a date such as LocalDate? What's the use case here?

EDIT: If you just want to know the number of days since the Unix epoch, you can skip most of this:

days = dateObj.getTime() / (24 * 60 * 60 * 1000);

You shouldn't be going through formatting at all just to get the year / month / day. Just create a Calendar, set the relevant time zone, call setTime with the dateObj you've already got, and then clear the hour/minute/second part of the calendar.

However, you should explicitly specify which time zone you want to consider - a Date represents an instant in time, which will mean different dates in different time zones.

You should also consider using Joda Time which makes all of this simpler and has a specific type for dates (LocalDate). That would also make it easy to find the number of days between the Unix epoch and a particular date without performing the division yourself.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I think you answered wrong question. According to his code he wants to get number of days since 1/1/1970. – AlexR Oct 31 '11 at 11:42
  • @AlexR: Well, it partly depends on what you mean by the date here, and what you mean by 1/1/1970. Is that the local epoch, or the Unix epoch? – Jon Skeet Oct 31 '11 at 11:44
  • I have to calculate the number of days since epoch and the input will be 2011-03-18 - no of day since epoch is 15051 .. – GKD Oct 31 '11 at 11:49
  • @GKD: Since the Unix epoch, i.e. UTC? If so, why bother with all the conversion at all? Why not just use your final line, but with `dateObj`? (Your input is a `Date` object, not a string - important difference.) – Jon Skeet Oct 31 '11 at 11:59
1

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:

You can convert the object of java.util.Date to Instant using Date#toInstant and then you can find the number of days from now until this date using ChronoUnit#between.

Demo:

import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.GregorianCalendar;

public class Main {
    public static void main(String[] args) {
        // A sample java.util.Date
        Date dateObj = GregorianCalendar.from(ZonedDateTime.of(2021, 10, 2, 22, 25, 0, 0, ZoneOffset.UTC)).getTime();

        Instant instant = dateObj.toInstant();

        // Difference between now and the given java.util.Date
        System.out.println(ChronoUnit.DAYS.between(Instant.now(), instant));
    }
}

Output:

99

ONLINE DEMO

Note that the above code calculates the number of days between two moments/instants represented in UTC. If you have date-time values local to a particular timezone, you need to specify the corresponding ZoneId.

Demo:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.GregorianCalendar;

public class Main {
    public static void main(String[] args) {
        ZoneId tz = ZoneId.of("Australia/Brisbane");

        // A sample java.util.Date representing the local date and time values in Australia/Brisbane
        Date dateObj = GregorianCalendar.from(ZonedDateTime.of(2021, 10, 2, 22, 25, 0, 0, tz)).getTime();

        // Difference between now in Australia/Brisbane and the given java.util.Date
        System.out.println(ChronoUnit.DAYS.between(Instant.now().atZone(tz), dateObj.toInstant().atZone(tz)));
    }
}

Output:

98

ONLINE DEMO

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.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110