回答編集履歴

6 訂正

swordone

swordone score 15547

2016/02/25 17:07  投稿

Java8が使えるなら、PeriodとDurationを合わせて使うという方法もあります。
```java
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
public class Q28238 {
   public static void main(String[] args) {
       LocalDateTime start = LocalDateTime.parse("2014/12/25 23:45:23", DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss"));
       LocalDateTime now = LocalDateTime.now();
       // 初日を1日目と数えるなら、その前の日を起点にすればいい
       LocalDate startLd = start.toLocalDate().minusDays(1);
       LocalDate nowLd = now.toLocalDate();
       Duration sec = Duration.between(start.toLocalTime(), now.toLocalTime());
       if(sec.isNegative()){
           sec = sec.plusDays(1);
           // 繰り下がり
           nowLd = nowLd.minusDays(1);
       }
       Period days = Period.between(start.toLocalDate(), nowLd);
       Period days = Period.between(startLd, nowLd);
       StringBuilder builder = new StringBuilder();
       builder.append(days.getYears()).append("年")
           .append(days.getMonths()).append("ヶ月")
           .append(days.getDays()).append("日 ")
           .append(sec.toHours()).append("時間")
           .append(sec.toMinutes() % 60).append("分")
           .append(sec.getSeconds() % 60).append("秒経過");
       System.out.println("start\t= " + start);
       System.out.println("now\t\t= " + now);
       System.out.println(builder);
   }
}
```
出力例:
start = 2014-12-20T23:45:23
now = 2016-02-25T11:31:27.787
1年2ヶ月4日 11時間46分4秒経過
---
Java7以下なら、Calendarクラスを最大限利用してこうなるかと…
日数については、例えば2/25->3/25の場合、2月の日数分経過していることになるので、
2/25->3/24の場合は(ゴールの年の2月の日数)-(足りない日数)になるという考えで計算しました。
```java
import static java.util.Calendar.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class Q28238_2 {
   static int[] units = { YEAR, MONTH, DAY_OF_MONTH, HOUR_OF_DAY, MINUTE, SECOND };
   public static void main(String[] args) throws ParseException {
       Date start = new SimpleDateFormat("yyyy'/'MM'/'dd HH:mm:ss", Locale.JAPANESE).parse("2016/1/24 12:34:12");
       Date today = new SimpleDateFormat("yyyy'/'MM'/'dd HH:mm:ss", Locale.JAPANESE).parse("2016/1/25 00:10:00");
       int[] result = new int[units.length];
       Calendar sCal = getInstance();
       Calendar tCal = getInstance();
       sCal.setTime(start);
       tCal.setTime(today);
       for (int i = units.length - 1; i >= 0; i--) {
           // 同じ単位同士で引き算
           result[i] = tCal.get(units[i]) - sCal.get(units[i]);
           // マイナスになった場合は繰り下がり処理
           if (result[i] < 0) {
               tCal.add(units[i - 1], -1);
               int add = tCal.getActualMaximum(units[i]);
               result[i] += (units[i] == DAY_OF_MONTH) ? add : add + 1;
           }
       }
       // 何年何か月という書式にするのが面倒だったので、配列そのまま出力するコードになってます
       System.out.println(Arrays.toString(result));
   }
}
```
5 初日を1日と数えるなら、初日を1日巻き戻せばOK

swordone

swordone score 15547

2016/02/25 16:08  投稿

Java8が使えるなら、PeriodとDurationを合わせて使うという方法もあります。
```java
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
public class Q28238 {
   public static void main(String[] args) {
       LocalDateTime start = LocalDateTime.parse("2014/12/25 23:45:23", DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss"));
       LocalDateTime now = LocalDateTime.now();
       // 初日を1日目と数えるなら、その前の日を起点にすればいい  
       LocalDate startLd = start.toLocalDate().minusDays(1);  
       LocalDate nowLd = now.toLocalDate();
       Duration sec = Duration.between(start.toLocalTime(), now.toLocalTime());
       if(sec.isNegative()){
           sec = sec.plusDays(1);
           // 繰り下がり
           nowLd = nowLd.minusDays(1);
       }
       Period days = Period.between(start.toLocalDate(), nowLd);
       StringBuilder builder = new StringBuilder();
       builder.append(days.getYears()).append("年")
           .append(days.getMonths()).append("ヶ月")
           .append(days.getDays()).append("日 ")
           .append(sec.toHours()).append("時間")
           .append(sec.toMinutes() % 60).append("分")
           .append(sec.getSeconds() % 60).append("秒経過");
       System.out.println("start\t= " + start);
       System.out.println("now\t\t= " + now);
       System.out.println(builder);
   }
}
```
出力例:
start = 2014-12-20T23:45:23
now = 2016-02-25T11:31:27.787
1年2ヶ月4日 11時間46分4秒経過
---
Java7以下なら、Calendarクラスを最大限利用してこうなるかと…
日数については、例えば2/25->3/25の場合、2月の日数分経過していることになるので、
2/25->3/24の場合は(ゴールの年の2月の日数)-(足りない日数)になるという考えで計算しました。
```java
import static java.util.Calendar.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class Q28238_2 {
   static int[] units = { YEAR, MONTH, DAY_OF_MONTH, HOUR_OF_DAY, MINUTE, SECOND };
   public static void main(String[] args) throws ParseException {
       Date start = new SimpleDateFormat("yyyy'/'MM'/'dd HH:mm:ss", Locale.JAPANESE).parse("2016/1/24 12:34:12");
       Date today = new SimpleDateFormat("yyyy'/'MM'/'dd HH:mm:ss", Locale.JAPANESE).parse("2016/1/25 00:10:00");
       int[] result = new int[units.length];
       Calendar sCal = getInstance();
       Calendar tCal = getInstance();
       sCal.setTime(start);
       tCal.setTime(today);
       for (int i = units.length - 1; i >= 0; i--) {
           // 同じ単位同士で引き算
           result[i] = tCal.get(units[i]) - sCal.get(units[i]);
           // マイナスになった場合は繰り下がり処理
           if (result[i] < 0) {
               tCal.add(units[i - 1], -1);
               int add = tCal.getActualMaximum(units[i]);
               result[i] += (units[i] == DAY_OF_MONTH) ? add : add + 1;
           }
       }
       // 何年何か月という書式にするのが面倒だったので、配列そのまま出力するコードになってます
       System.out.println(Arrays.toString(result));
   }
}
```
4 初日を1日と数えるなら,

swordone

swordone score 15547

2016/02/25 16:06  投稿

Java8が使えるなら、PeriodとDurationを合わせて使うという方法もあります。
```java
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
public class Q28238 {
public static void main(String[] args) {
LocalDateTime start = LocalDateTime.parse("2014/12/25 23:45:23", DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss"));
LocalDateTime now = LocalDateTime.now();
LocalDate nowLd = now.toLocalDate();
Duration sec = Duration.between(start.toLocalTime(), now.toLocalTime());
if(sec.isNegative()){
sec = sec.plusDays(1);
// 繰り下がり
nowLd = nowLd.minusDays(1);
}
Period days = Period.between(start.toLocalDate(), nowLd);
StringBuilder builder = new StringBuilder();
builder.append(days.getYears()).append("年")
.append(days.getMonths()).append("ヶ月")
.append(days.getDays()).append("日 ")
.append(sec.toHours()).append("時間")
.append(sec.toMinutes() % 60).append("分")
.append(sec.getSeconds() % 60).append("秒経過");
System.out.println("start\t= " + start);
System.out.println("now\t\t= " + now);
System.out.println(builder);
}
}
```
出力例:
start = 2014-12-20T23:45:23
now = 2016-02-25T11:31:27.787
1年2ヶ月4日 11時間46分4秒経過
---
Java7以下なら、Calendarクラスを最大限利用してこうなるかと…
日数については、例えば2/25->3/25の場合、2月の日数分経過していることになるので、
2/25->3/24の場合は(ゴールの年の2月の日数)-(足りない日数)になるという考えで計算しました。
```java
import static java.util.Calendar.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class Q28238_2 {
static int[] units = { YEAR, MONTH, DAY_OF_MONTH, HOUR_OF_DAY, MINUTE, SECOND };
public static void main(String[] args) throws ParseException {
Date start = new SimpleDateFormat("yyyy'/'MM'/'dd HH:mm:ss", Locale.JAPANESE).parse("2016/1/24 12:34:12");
Date today = new SimpleDateFormat("yyyy'/'MM'/'dd HH:mm:ss", Locale.JAPANESE).parse("2016/1/25 00:10:00");
int[] result = new int[units.length];
Calendar sCal = getInstance();
Calendar tCal = getInstance();
sCal.setTime(start);
tCal.setTime(today);
for (int i = units.length - 1; i >= 0; i--) {
// 同じ単位同士で引き算
result[i] = tCal.get(units[i]) - sCal.get(units[i]);
// マイナスになった場合は繰り下がり処理
if (result[i] < 0) {
tCal.add(units[i - 1], -1);
int add = tCal.getActualMaximum(units[i]);
result[i] += (units[i] == DAY_OF_MONTH) ? add : add + 1;
}
}
// 何年何か月という書式にするのが面倒だったので、配列そのまま出力するコードになってます
System.out.println(Arrays.toString(result));
}
}
```
3 Java8の方でも繰り下がり考慮したコードに変更

swordone

swordone score 15547

2016/02/25 15:51  投稿

Java8が使えるなら、PeriodとDurationを合わせて使うという方法もあります。
```java
import java.time.Duration;
import java.time.LocalDate;  
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
public class Q28238 {
   public static void main(String[] args) {
       //文字列を時刻に変換
       LocalDateTime start = LocalDateTime.parse("2014/12/20 23:45:23", DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss"));
       //現在時刻を取得
       LocalDateTime start = LocalDateTime.parse("2014/12/25 23:45:23", DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss"));
       LocalDateTime now = LocalDateTime.now();
       //日付を元に期間(日数以上)を計算
       Period days = Period.between(start.toLocalDate(), now.toLocalDate());
       //時刻を元に期間(日数未満)を計算
       LocalDate nowLd = now.toLocalDate();
       Duration sec = Duration.between(start.toLocalTime(), now.toLocalTime());
       //時刻ベースで現在のほうが前(startが12時に対し現在が8時など)の場合、時刻期間がマイナスになるため、日付から一日移動して調整  
       if(sec.isNegative()){
           sec = sec.plusDays(1);
           days = days.minusDays(1);
           // 繰り下がり
           nowLd = nowLd.minusDays(1);
       }
       Period days = Period.between(start.toLocalDate(), nowLd);  
       StringBuilder builder = new StringBuilder();
       builder.append(days.getYears()).append("年")
           .append(days.getMonths()).append("ヶ月")
           .append(days.getDays()).append("日 ")
           .append(sec.toHours()).append("時間")
           .append(sec.toMinutes() % 60).append("分")
           .append(sec.getSeconds() % 60).append("秒経過");
       System.out.println("start = " + start);
       System.out.println("now = " + now);
       System.out.println("start\t= " + start);
       System.out.println("now\t\t= " + now);
       System.out.println(builder);
   }
}
```
出力例:
start = 2014-12-20T23:45:23
now = 2016-02-25T11:31:27.787
1年2ヶ月4日 11時間46分4秒経過
---
Java7以下なら、Calendarクラスを最大限利用してこうなるかと…
日数については、例えば2/25->3/25の場合、2月の日数分経過していることになるので、
2/25->3/24の場合は(ゴールの年の2月の日数)-(足りない日数)になるという考えで計算しました。
```java
import static java.util.Calendar.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class Q28238_2 {
   static int[] units = { YEAR, MONTH, DAY_OF_MONTH, HOUR_OF_DAY, MINUTE, SECOND };
   public static void main(String[] args) throws ParseException {
       Date start = new SimpleDateFormat("yyyy'/'MM'/'dd HH:mm:ss", Locale.JAPANESE).parse("2016/1/24 12:34:12");
       Date today = new SimpleDateFormat("yyyy'/'MM'/'dd HH:mm:ss", Locale.JAPANESE).parse("2016/1/25 00:10:00");
       int[] result = new int[units.length];
       Calendar sCal = getInstance();
       Calendar tCal = getInstance();
       sCal.setTime(start);
       tCal.setTime(today);
       for (int i = units.length - 1; i >= 0; i--) {
           // 同じ単位同士で引き算
           result[i] = tCal.get(units[i]) - sCal.get(units[i]);
           // マイナスになった場合は繰り下がり処理
           if (result[i] < 0) {
               tCal.add(units[i - 1], -1);
               int add = tCal.getActualMaximum(units[i]);
               result[i] += (units[i] == DAY_OF_MONTH) ? add : add + 1;
           }
       }
       // 何年何か月という書式にするのが面倒だったので、配列そのまま出力するコードになってます
       System.out.println(Arrays.toString(result));
   }
}
```
2 Calendarを使う場合のコード追記

swordone

swordone score 15547

2016/02/25 15:48  投稿

Java8が使えるなら、PeriodとDurationを合わせて使うという方法もあります。
```java
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
public class Q28238 {
   public static void main(String[] args) {
       //文字列を時刻に変換
       LocalDateTime start = LocalDateTime.parse("2014/12/20 23:45:23", DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss"));
       //現在時刻を取得
       LocalDateTime now = LocalDateTime.now();
       //日付を元に期間(日数以上)を計算
       Period days = Period.between(start.toLocalDate(), now.toLocalDate());
       //時刻を元に期間(日数未満)を計算
       Duration sec = Duration.between(start.toLocalTime(), now.toLocalTime());
       //時刻ベースで現在のほうが前(startが12時に対し現在が8時など)の場合、時刻期間がマイナスになるため、日付から一日移動して調整
       if(sec.isNegative()){
           sec = sec.plusDays(1);
           days = days.minusDays(1);
       }
       StringBuilder builder = new StringBuilder();
       builder.append(days.getYears()).append("年")
           .append(days.getMonths()).append("ヶ月")
           .append(days.getDays()).append("日 ")
           .append(sec.toHours()).append("時間")
           .append(sec.toMinutes() % 60).append("分")
           .append(sec.getSeconds() % 60).append("秒経過");
       System.out.println("start = " + start);
       System.out.println("now = " + now);
       System.out.println(builder);
   }
}
```
出力例:
start = 2014-12-20T23:45:23
now = 2016-02-25T11:31:27.787
1年2ヶ月4日 11時間46分4秒経過
1年2ヶ月4日 11時間46分4秒経過
---
Java7以下なら、Calendarクラスを最大限利用してこうなるかと…
日数については、例えば2/25->3/25の場合、2月の日数分経過していることになるので、
2/25->3/24の場合は(ゴールの年の2月の日数)-(足りない日数)になるという考えで計算しました。
```java
import static java.util.Calendar.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class Q28238_2 {
   static int[] units = { YEAR, MONTH, DAY_OF_MONTH, HOUR_OF_DAY, MINUTE, SECOND };
   public static void main(String[] args) throws ParseException {
       Date start = new SimpleDateFormat("yyyy'/'MM'/'dd HH:mm:ss", Locale.JAPANESE).parse("2016/1/24 12:34:12");
       Date today = new SimpleDateFormat("yyyy'/'MM'/'dd HH:mm:ss", Locale.JAPANESE).parse("2016/1/25 00:10:00");
       int[] result = new int[units.length];
       Calendar sCal = getInstance();
       Calendar tCal = getInstance();
       sCal.setTime(start);
       tCal.setTime(today);
       for (int i = units.length - 1; i >= 0; i--) {
           // 同じ単位同士で引き算
           result[i] = tCal.get(units[i]) - sCal.get(units[i]);
           // マイナスになった場合は繰り下がり処理
           if (result[i] < 0) {
               tCal.add(units[i - 1], -1);
               int add = tCal.getActualMaximum(units[i]);
               result[i] += (units[i] == DAY_OF_MONTH) ? add : add + 1;
           }
       }
       // 何年何か月という書式にするのが面倒だったので、配列そのまま出力するコードになってます
       System.out.println(Arrays.toString(result));
   }
}
```
1 余計なパッケージ宣言を削除

swordone

swordone score 15547

2016/02/25 11:44  投稿

Java8が使えるなら、PeriodとDurationを合わせて使うという方法もあります。
```java
package teratail;  
 
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
public class Q28238 {
   public static void main(String[] args) {
       //文字列を時刻に変換
       LocalDateTime start = LocalDateTime.parse("2014/12/20 23:45:23", DateTimeFormatter.ofPattern("uuuu/MM/dd HH:mm:ss"));
       //現在時刻を取得
       LocalDateTime now = LocalDateTime.now();
       //日付を元に期間(日数以上)を計算
       Period days = Period.between(start.toLocalDate(), now.toLocalDate());
       //時刻を元に期間(日数未満)を計算
       Duration sec = Duration.between(start.toLocalTime(), now.toLocalTime());
       //時刻ベースで現在のほうが前(startが12時に対し現在が8時など)の場合、時刻期間がマイナスになるため、日付から一日移動して調整
       if(sec.isNegative()){
           sec = sec.plusDays(1);
           days = days.minusDays(1);
       }
       StringBuilder builder = new StringBuilder();
       builder.append(days.getYears()).append("年")
           .append(days.getMonths()).append("ヶ月")
           .append(days.getDays()).append("日 ")
           .append(sec.toHours()).append("時間")
           .append(sec.toMinutes() % 60).append("分")
           .append(sec.getSeconds() % 60).append("秒経過");
       System.out.println("start = " + start);
       System.out.println("now = " + now);
       System.out.println(builder);
   }
}
```
出力例:
start = 2014-12-20T23:45:23
now = 2016-02-25T11:31:27.787
1年2ヶ月4日 11時間46分4秒経過

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る