0

IMPORTANT: external libraries, Date and Instant class are not allowed

You may not use any library routines for manipulation of time or dates, such as converting UNIX time to a date string or for formatting date strings in general. All calculations for determining year, month, day, and time must appear in your source.

I wrote this program to convert from UNIX time (time in seconds since 12:00 AM January 1, 1970) to normal date and time. At first glance it seems to work fine, but in some tests it was off by exactly one day. The hours, minutes, months, and years are always correct, but the days are one too few.

For example, when using UNIX time 1234567890 the program produces 11:31 PM 02/13/2009, which is correct! However when inputing 1111111111 (10 1's), the program produces 1:58 AM 03/17/2005, where it should output 01:58 AM 03/18/2005. 64075132196 produces 7:49 AM 06/17/4000 (correct) but 95632040996 produces 7:49 AM 06/16/5000, where it should be the 17th day instead of the 16th.

In order to check my program, I entered a date and time into https://www.unixtimestamp.com/ and entered the resulting UNIX time into my program. (This is how I managed to get exact UNIX codes in the troubleshooting above).

I would appreciate help finding this error and additionally implementing a more efficient solution to this problem altogether.

import java.util.*;
class Main {
  public static void main(String[] args) {
    System.out.println("\nEnter UNIX time");
    Scanner scan = new Scanner(System.in);
    int[] monthDays = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    int[] leapYearMonthDays = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    long unix = scan.nextLong();
    int years = 0, months = 0, days = 0, hours = 0, minutes = 0;

    boolean leapYear = false;
    String AMPM = "AM";
    
    while (unix >= 60) {
      unix -= 60;
      minutes++;
      
      if (minutes >= 60) {
        minutes -= 60;
        hours++;
      }
      if (hours >= 24) {
        hours -= 24;
        days++;
      }
      if (leapYear) {
        if (days >= leapYearMonthDays[months]) {
          days -= leapYearMonthDays[months];
          months++;
        }
      }
      else {
        if (days >= monthDays[months]) {
          days -= monthDays[months];
          months++;
        }
      }
      if (months >= 12) {
        if (isLeapYear(1970 + years)) leapYear = true; else leapYear = false;
        months -= 12;
        years++;
      }
    }
    
    if (hours > 12) {
      AMPM = "PM";
      hours -= 12;
    }
    
    if (days == 0) days = 1;
    String daysString = String.valueOf(days);
    if (daysString.length() == 1) daysString = "0" + daysString;
    String monthsString = String.valueOf(months + 1);
    if (monthsString.length() == 1) monthsString = "0" + monthsString;
    String minutesString = String.valueOf(minutes);
    if (minutesString.length() == 1) minutesString = "0" + minutesString;
    if (hours == 0) hours = 12;

    System.out.println("\n" + hours + ":" + minutesString + " " + AMPM + "  " + monthsString + "/" + daysString + "/" + (years + 1970));
  }

  public static boolean isLeapYear (int year) {
    if (year % 4 == 0) {
      if (year % 100 == 0) {
        if (year % 400 == 0) {
          return true;
        }
        else return false;
      }
      else return true;
    }
    return false;
  }
}
Roy A.
  • 3
  • 2
  • this looks like a homework assignment, perhaps reaching out to your instructors for advice on how to identify problems in your code. – Kevin Crum Jul 11 '22 at 17:28
  • 1
    Start simple. A day in UTC (I assume that you are assuming UTC) is 86 400 seconds, so entering 86400 should give January 2, 1970 00:00. I got `12:00 AM 01/01/1970`. Start by finding and fixing this bug. After that there are probably more. – Ole V.V. Jul 11 '22 at 17:58
  • If this is a schoolwork assignment, say so explicitly at the top of your Question. – Basil Bourque Jul 11 '22 at 20:05

2 Answers2

1

You created your own code. That probably was the intent of the homework. Now pinpoint the problem.

For that you can actually create a loop generating different Unix time values. For each of these values calculate the date using your code, in parallel calculate the date using java.util.Date or java.util.Instant. Compare the dates and print results suitable so you can pinpoint the situations where your code produces deviations. Try to understand the deviations and improve your code.

With that you would not only exercise coding date calculations but also automated testing or test driven development.

Queeg
  • 7,748
  • 1
  • 16
  • 42
-1

Given

UNIX time (time in seconds since 12:00 AM January 1, 1970)

Assume if we convert 0 as integer timestmap in unix-epoch format to a java.util.Date we solved it.

Using java.util.Date (prior to Java 8)

long unixTimeInMilliseconds = 0; 
Date convertedDate = new java.util.Date(unixTimeInMilliseconds);
System.out.println(convertedDate);

Prints:

Thu Jan 01 00:00:00 GMT 1970

Using java.time.Instant or suitable Java 8 class

You can also use the Java Date/Time API introduced since Java 8 in a similar manner:

long unixTimeInMilliseconds = 0; // 0 ms
Instant timestamp = Instant.ofEpochMilli(unixTimeInMilliseconds);
System.out.println(timestamp);

Prints:

1970-01-01T00:00:00Z

See also

Unix epoch time to Java Date object

hc_dev
  • 8,389
  • 1
  • 26
  • 38
  • 1
    I strongly recommend you don’t use `Date`. That class is poorly designed and long outdated. Instead use `Instant` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). It also — contrary to `Date` — supports seconds and not only milliseconds. – Ole V.V. Jul 11 '22 at 17:56
  • 1
    Only very outdated curricula. The Java community officially abandoned `Date` 8 years ago. I certainly hope that it is not taught any more. – Ole V.V. Jul 11 '22 at 18:15
  • @OleV.V. you should really write an answer to teach modern Java Date/Time handling. – hc_dev Jul 11 '22 at 18:21
  • 1
    Thanks. Also thanks for showing the preferred way using `Instant`. I am awaiting an answer to my question whether java.time is forbidden as external before pushing it further. Also I am no longer contributing answers here (for reasons that I try to explain in [my profile](https://stackoverflow.com/users/5772882/ole-v-v)), but count on a helpful comment from me in case the OP deems java.time within bounds. – Ole V.V. Jul 11 '22 at 18:25
  • 1
    Much appreciated feedback and efficient solutions, however I am required to show the calculations: I cannot use any type of class that already coverts UNIX to date and time. "You may not use any library routines for manipulation of time or dates, such as converting UNIX time to a date string or for formatting date strings in general. All calculations for determining year, month, day, and time must appear in your source." – Roy A. Jul 11 '22 at 18:36
  • 2
    Thanks, @RoyA., for quoting the more precise requirements. I pasted them into your question. It’s really where they belong. – Ole V.V. Jul 11 '22 at 18:49