简体   繁体   中英

Converting a float number to years, months, weeks, days

I've been trying to convert a float number to years, months, weeks, days, hours, minutes and seconds but I'm not getting it.

For example, if the user enters 768.96 the total would be 2 years, 1 month, 1 week, 1 day, 23 hours, 0 minutes and 2 seconds.

This is what I have.

import javax.swing.JOptionPane;

public class timePartition {

public static void main(String[] args) {

   float totalTime;
   float userInput;
   int years = 0, months = 0, weeks = 0, days = 0, hours = 0, minutes = 0, seconds = 0;


   do{
       userInput = Float.parseFloat(JOptionPane.showInputDialog("Enter a positive number to decompose")); 
       totalTime = userInput;

       years = (int) userInput / 365;
       userInput = userInput % 10; 

       months = (int) userInput / 12;
       userInput = userInput % 10; 

       weeks = (int) userInput / 4;
       userInput = userInput % 10;

       days = (int) userInput / 30;
       userInput = userInput % 10;

       hours = (int) userInput / 24;
       userInput = userInput % 10;

       minutes = (int) userInput / 60;
       userInput = userInput % 10;

       seconds = (int) userInput / 60;
       userInput = userInput % 10;


    }while (userInput >=1);

    System.out.print("The number " +totalTime+ " is " +years+ " years, " +months+ " months, " +weeks+ " weeks, " +days+ " days, " +hours+ " hours, " +minutes+ " minutes, " +seconds+ " seconds.");


}

I don't think you can use modulo 10 to reduce the input after you pull out each of the denominations. Also, you don't need a while loop at all for this.

You have to do something like

years = (int) (userInput / 365);
userInput = userInput - years*365;

and so on. Also, since the input is in days, you have to keep thinking in days when you divide out, so dividing by 12 to get the number of months doesn't make sense. You would instead divide by 30, 31 or 28. Similarly for hours, you would have to multiply the remaining fraction of days by 24, and then take the fractional part of the hours and decompose it similarly into minutes and seconds.

I suppose the input is in day.
There are few strange thing in your code :

  • the while loop is not necessary
  • (int) userInput will cast userInput in int before the division, not really important here, but be careful ;)
  • userInput % 10 everywhere
  • divide by 12 to get the number of month, by 4 to get the number of weeks, and so on

Here is a skeleton of the solution:

float userInput /* = ... */ ;

int years = (int)(userInput/365) ;
userInput = userInput - years*365 ; // or userInput%365 ;

int month = (int)(userInput/30);
userInput = userInput - month*30 ; // or userInput%30 ;

int day = (int) userInput ;
userInput = userInput - day ;

userInput = userInput * 24 ; //transform in hours

int hours = (int)hours ;
userInput = userInput - hours ;

userInput = userInput * 60 ; // transform in minute

int minutes = (int)userInput ;
userInput = userInput - minutes ;

userInput = userInput * 60 ; // transform in second

int seconds = (int) userInput ;

Ok, several things here:

  • just to make sure you're aware: date/time arithmetic is not as simple as it may seem. Several fields are not uniform in duration, including years (due to leap years in some years but not others), months (28-31 days depending on the month), and even minutes (due to rare but strictly necessary leap seconds). This means that technically you can't properly decompose a total duration count (eg "x days") into duration fields, and vice-versa (at least not without some "anchoring" date/time point).
  • if you want to make incorrect assumptions like "all years have exactly 365 days" and "all months have exactly 30 days" and "all minutes have exactly 60 seconds" then this can be done.
  • I'm not sure whether you wanted your program to take and decompose a single value, in which case the loop is not necessary, or multiple values, in which case the final print statement should be inside the loop. I've assumed the latter.
  • based on your example input and the start of your decomposition code, it appears that you want the integral part of the input float value to represent a number of days, with the fractional part representing a time value as a fraction of one day. Your decomposition code is incorrect according to this interpretation; you first must separate the ipart and fpart to decompose independently, and in each step of the decomposition, you must take the remainder on the previous field duration size (eg 7 days for a week, 3600 seconds for an hour), rather than a fixed value of 10 (not sure where that came from...) to prepare for the next step of the decomposition. This can be done with the mod-assign operator %= .

Here's working code:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class TimePartition {

    public static void main(String[] args) throws Exception {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        while (true) {

            System.out.println("Enter a positive number to decompose");
            String input = br.readLine();
            if (input.equals("")) break;
            float inputAsFloat = Float.parseFloat(input);
            if (inputAsFloat == 0.0) break;

            // the input is an integral day count, with a possible fractional part representing time as a fraction of one day
            int totalDays = (int)inputAsFloat;
            int totalSeconds = (int)((inputAsFloat-totalDays)*60.0*60.0*24.0);

            // decompose totalDays into date fields
            int years = 0;
            int months = 0;
            int weeks = 0;
            int days = 0;

            // ignores leap years
            years = (int)totalDays/365;
            totalDays %= 365;

            // assumes all months have 30 days
            months = (int)totalDays/30;
            totalDays %= 30;

            weeks = (int)totalDays/7;
            totalDays %= 7;

            days = (int)totalDays;

            // decompose totalSeconds into time fields
            int hours = 0;
            int minutes = 0;
            int seconds = 0;

            hours = (int)totalSeconds/3600;
            totalSeconds %= 3600;

            // ignores leap seconds
            minutes = (int)totalSeconds/60;
            totalSeconds %= 60;

            seconds = (int)totalSeconds;

            System.out.println("The number "+inputAsFloat+" is "+years+" years, "+months+" months, "+weeks+" weeks, "+days+" days, "+hours+" hours, "+minutes+" minutes, "+seconds+" seconds.");

        } // end while

    } // end main()

} // end class TimePartition

Demo:

bash> ls
TimePartition.java

bash> javac TimePartition.java

bash> ls
TimePartition.class*  TimePartition.java

bash> CLASSPATH=. java TimePartition
Enter a positive number to decompose
768.96
The number 768.96 is 2 years, 1 months, 1 weeks, 1 days, 23 hours, 2 minutes, 25 seconds.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM