users@jaxb.java.net

Re: Better xs:duration support?

From: Malachi de AElfweald <malachi_at_EOTI.ORG>
Date: Thu, 24 Jul 2003 12:17:49 -0600

Ok, kinda lengthy, but I think this bit of code should solve everyone's use case.... Feel free to scavenge it for JAXB :)

package com.temporalwave.util;

import java.util.*;

/**
 * Parse or Create XML Schema dataType "duration"
 */
public class XSDuration
{
 public static final int YEARS = 0;
 public static final int MONTHS = 1;
 public static final int DAYS = 2;
 public static final int HOURS = 3;
 public static final int MINUTES = 4;
 public static final int SECONDS = 5;

 protected int years = 0;
 protected int months = 0;
 protected int days = 0;
 protected int hours = 0;
 protected int minutes = 0;
 protected int seconds = 0;

 public XSDuration()
 {
 }

 public XSDuration(String duration)
 {
  this();
  parse(duration);
 }

 public void parse(String duration)
 {
  int tNdx = duration.indexOf("T");
  String date, time;
  if(tNdx == -1)
  {
   date = duration.substring(1);
   time = "";
  }else{
   date = duration.substring(1,tNdx);
   time = duration.substring(tNdx + 1);
  }

  int num = 0;
  char c;

  for(int pos=0; pos<date.length(); pos++)
  {
   c = date.charAt(pos);
   if(Character.isDigit(c))
   {
    num = (num * 10) + Integer.parseInt("" + c);
   }else{
    if( (c == 'Y') || (c == 'y') )
     years = num;
    else if( (c == 'M') || (c == 'm') )
     months = num;
    else if( (c == 'D') || (c == 'd') )
     days = num;

    num = 0;
   }
  }

  for(int pos=0; pos<time.length(); pos++)
  {
   c = time.charAt(pos);
   if(Character.isDigit(c))
   {
    num = (num * 10) + Integer.parseInt("" + c);
   }else{
    if( (c == 'H') || (c == 'h') )
     hours = num;
    else if( (c == 'M') || (c == 'm') )
     minutes = num;
    else if( (c == 'S') || (c == 's') )
     seconds = num;

    num = 0;
   }
  }
 }

 public String format()
 {
  StringBuffer buf = new StringBuffer();
  buf.append("P");
  if(years >0) buf.append(years + "Y");
  if(months >0) buf.append(months + "M");
  if(days >0) buf.append(days + "D");
  if( (hours+minutes+seconds) > 0)
  {
   buf.append("T");
   if(hours > 0) buf.append(hours + "H");
   if(minutes > 0) buf.append(minutes + "M");
   if(seconds > 0) buf.append(seconds + "S");
  }
  return buf.toString();
 }

 public void set(int field, int value)
 {
  switch(field)
  {
   case YEARS: years=value;break;
   case MONTHS: months=value;break;
   case DAYS: days=value;break;
   case HOURS: hours=value;break;
   case MINUTES: minutes=value;break;
   case SECONDS: seconds=value;break;
  }
 }

 public int get(int field)
 {
  switch(field)
  {
   case YEARS: return years;
   case MONTHS: return months;
   case DAYS: return days;
   case HOURS: return hours;
   case MINUTES: return minutes;
   case SECONDS: return seconds;
  }

  return -1;
 }

 public void addTo(Calendar cal)
 {
  cal.add(cal.YEAR, years);
  cal.add(cal.MONTH, months);
  cal.add(cal.DAY_OF_MONTH, days);
  cal.add(cal.HOUR, hours);
  cal.add(cal.MINUTE, minutes);
  cal.add(cal.SECOND, seconds);
 }

 public long getMilliseconds()
 {
  Calendar now = Calendar.getInstance();
  long current = now.getTimeInMillis();
  addTo(now);
  long future = now.getTimeInMillis();
  return future-current;
 }

 public String toString(){return format();}

 public static void main(String[] args)
 {
  if(args.length != 1)
  {
   System.out.println("USAGE: java -cp TWCommon.jar com.temporalwave.util.XSDuration PERIOD");
   System.out.println("Where PERIOD is something like 'P5Y2M10DT15H3M20S'");
   System.exit(1);
  }

  XSDuration duration = new XSDuration(args[0]);
  System.out.println(args[0]);
  System.out.println("----------------------------------");
  System.out.println("YEARS:\t\t" + duration.get(YEARS));
  System.out.println("MONTHS:\t\t"+ duration.get(MONTHS));
  System.out.println("DAYS:\t\t" + duration.get(DAYS));
  System.out.println("HOURS:\t\t" + duration.get(HOURS));
  System.out.println("MINUTES:\t" + duration.get(MINUTES));
  System.out.println("SECONDS:\t" + duration.get(SECONDS));
  System.out.println("----------------------------------");
  System.out.println("Total Milliseconds: " + duration.getMilliseconds());
  Calendar now = Calendar.getInstance();
  System.out.println("NOW:\t\t" + now.getTime());
  duration.addTo(now);
  System.out.println("+Duration:\t" + now.getTime());
  System.out.println("----------------------------------");
  System.out.println(duration);
 }
}