Datas intercaladas

11 respostas
S

Oi Gente…
Estou com uma dúvida em relação as datas.

Eu tenho que fazer uma comparação que me retornem se dois períodos de datas se intercalam.
Exemplo I:
1º Período: 01/01/2008 à 31/01/2008
2º período: 15/01/2008 à 15/02/2008
Nesse caso a resposta seria positiva pois 15/01/2008 está entre 01/01/2008 e 31/01/2008

Exemplo II:
1º Período: 01/01/2008 à 31/01/2008
2º período: 01/02/2008 à 15/02/2008
Nesse caso a resposta seria negativa pois o segundo período inicia-se após o primeiro.

Um vez eu fiz uma consulta no Oracle usando between que funcionava.
Será que existe alguma coisa semelhante para JAVA???

Agradeço e comemoro a volta ao JAVA depois de dois anos programando proceduralmente em PHP :frowning:

11 Respostas

M

Olá, você pode utilizar os métodos after() e before() da classe Calendar.

B

eh soh uma ideia, mas acredito que pode ser mais simples do que parece…

vc compara a data final do primeiro periodo com a inicial do segundo…

  • compara os anos;
  • se true, compara os meses;
  • se true compara as datas;

soh uma ideia viu…

M

Pegue a data como um todo! Dê uma estudada na classe Calendar. Não fique manuseando dias, meses e anos separadamente. É um trabalho desnecessário, é só estudar um pouco a API. Abraços.

S

santina.mota:
Oi Gente…
Estou com uma dúvida em relação as datas.

Eu tenho que fazer uma comparação que me retornem se dois períodos de datas se intercalam.

Vc quer saber se se intersectam. Não é tão simples quanto parece.
Eis uma classe que implementa o conceito de intervalo que pode ser usada para testar intersecção

Ela funciona com qualquer coisa que seja comparável. No caso Date.

public class Interval<T> {

	
	protected T start;
	protected T end;
	protected Comparator<? super T> comparator;


	public final static <V> Interval<V> emptyInterval(){
		return new Interval<V>(new ComparableComparator<V>());
	}

	public final static <V> Interval<V> emptyInterval(Comparator<? super V> comparator){
		return new Interval<V>(comparator);
	}
	

	/**
	 * Creates a Interval from the values of two comparable objects. 
	 * @param start start of the Interval
	 * @param end end of the Interval
	 * @throws IllegalArgumentException if start is not less than end or their are null
	 * @throws ClassCastException if the values are not <code>Comparable</code>.
	 * @return a <code>Interval</code> from <code>start</code> to <code>end</code>
	 */
	public final static <V extends Comparable<V>> Interval<V> between(V start, V end){
		return between(start,end,new ComparableComparator<V>());
	} 

	/**
	 * Creates a Interval from the values of two objects and a <code>Comparator</code> for those objects.
	 * @param <V>
	 * @param start start of the Interval
	 * @param end end of the Interval
	 * @param comparator <code>Comparator</code> encapsulating the rules of order for the passed object class
	 * @return a <code>Interval</code> from <code>start</code> to <code>end</code>
	 */
	public static <V> Interval<V> between(V start, V end, Comparator<? super V> comparator){
		if (comparator == null){
			throw new NullPointerException("A comparator is required.");
		}
		if (comparator.compare(start,end)>0){
			throw new IllegalArgumentException("Interval`s start must preceed its end");
		}

		return new Interval<V>(start,end,comparator);
	} 
	

    Interval(T start, T end,Comparator<? super T> comparator) {
		
		this.start = start;
		this.end = end;
		this.comparator = comparator;
	}

	/**
	 * @param start
	 * @param end
	 * @param comparator
	 */
   protected Interval(Comparator<? super T> comparator) {
		this.start = null;
		this.end = null;
		this.comparator = comparator;
	}


	/**
	 * @return Returns the end.
	 */
	public T end() {
		return end;
	}

	/**
	 * @return Returns the start.
	 */
	public T start() {
		return start;
	}

	/**
	 * The interval is empty if the start and end point are equal
	 * @return <code>true</code> if the interval is empty.
	 */
	public boolean isEmpty(){
		// first comparison is necessary as start and end can be null
		return start == end || start.equals(end);
	}



	/**
	 * Determines if this interval intersects another
	 * @param other the candidate to intersection
	 * @return <code>true</code> if <code>this</code> intersects <code>other</code>
	 */
	public boolean intersects (Interval<T> other){

		return !this.isEmpty() && !other.isEmpty() &&
		(this.contains(other.start, true, true) || 
				this.contains(other.end, true, true) || 
				other.contains(this.start, true, true) || 
				other.contains(this.end, true, true));


	}

	/**
	 * Determines this interval intersection with another
	 * @param other the interval to intersect
	 * @return an interval representing the intersections of the intervals
	 */
	public Interval<T> intersection (Interval<T> other){

		// is one is empty the intersection is empty
		if (this.isEmpty() || other.isEmpty()) {
			return new Interval<T>(this.comparator);
		}

		if (other.equals(this)){ // are the same. 
			return other;
		}

		if (this.intersects(other)) {
			// intersects
			return new Interval<T>( max(this.start, other.start), min(this.end, other.end) , comparator);
		} else {
			// does not intersect
			return new Interval<T>(this.comparator);
		}


	}

	/**
	 * The union of this Interval with an another. 
	 * The result is a Interval from the lowest start to the greatest end
	 * Note that union is a commutative operation,
	 * meaning that R.union(S).equals(S.union(R)) == true , R and S being instances of Interval.
	 * @param other
	 * @return a Interval from the lowest start to the greatest end. Example : [2,3] merged with [7,10]  will return [2,10] 
	 */
	public Interval<T> union (Interval<T> other){
		return new Interval<T> ( 
				min(this.start, other.start) , // start at the minor start
				max(this.end , other.end), // end at the major end
				this.comparator // the same comparator
		);
	}


	/**
	 * Determines if an object is between the start(inclusive) and end(inclusive) of the interval
	 * @param other the candidate object
	 * @return <code>true</code> if the object is in the interval , <code>false</code> otherwise
	 */
	public boolean contains(T value){
		return !this.isEmpty() && comparator.compare(value, start) >=0 && comparator.compare(value, end) <=0;
	}


	/**
	 * Determine if the value is contained in the Interval considering the start and the end 
	 * of the Interval as belonging, or not , to the Interval according with openLeft and openRight arguments
	 * @param value the value to test
	 * @param openStart if <code>true<code> test assuming the start of the interval does not belongs to the Interval.
	 * @param openEnd if <code>true<code> test assuming the end of the interval does not belongs to the Interval.
	 * @return
	 */
	public boolean contains(T value, boolean openStart , boolean openEnd){
		//return !this.isEmpty() && (openStart?comparator.compare(value, start) >0: comparator.compare(value, start) >=0 ) && 
		//(openEnd?comparator.compare(value, end) <0:comparator.compare(value, end) <=0);

		return !this.isEmpty() && comparator.compare(value, start) >=0 && comparator.compare(value, end) <=0;
	}


	/**
	 * Determines the maximum of two values using the 
	 * comparator
	 * @param a
	 * @param b
	 * @return the maximum between a and b
	 */
	protected T  max(T a , T b){
		if (comparator.compare(a,b)>=0){
			return a;
		}
		return b;
	}

	/**
	 * Determines the minimum of two values using the 
	 * comparator
	 * @param a
	 * @param b
	 * @return the minimum between a and b
	 */
	protected T  min(T a , T b){
		if (comparator.compare(a,b)<=0){
			return a;
		}
		return b;
	}

	public String toString(){
		if (this.isEmpty()){
			return "[]";
		}
		return "[" + start.toString() + " ; " +  end.toString() + "]";
	}


	/**
	 * Intervals are equal if the their starts are equal and their ends are equals
	 */
	@SuppressWarnings("unchecked")
	public boolean equals(Object other){
		return other instanceof Interval && this.equals((Interval)other);
	}

	/**
	 * Intervals are equal if their starts are equal and their ends are equals
	 */
	public boolean equals(Interval<T> other){
		return (this.isEmpty() && other.isEmpty() ) || // both are empty or the limits are equal
		( comparator.compare(start, other.start)==0 && comparator.compare(end, other.end)==0);
	}

}
M

Sérgio, você não é acha que é muito código somente para verificar se a menor data consta em um intervalo pré-determinado?
Acho que não precisa de um algoritmo tão genérico e grande. :smiley:

S

mfjeng:
Sérgio, você não é acha que é muito código somente para verificar se a menor data consta em um intervalo pré-determinado?
Acho que não precisa de um algoritmo tão genérico e grande. :smiley:

Eu não acho nada. O problema não se resolve apenas usando Calendar , liás nada tem a haver com Calendar. Nem Date já agora. A classe é grande de mais ? é muito código ? Classes medem-se por metro agora ?
Se é muito grande corta as partes que não quer. O que interessa é que o algoritmo ( que são duas linhas ) só funciona ( em duas linhas) com uma estrutura do tipo intervalo.

Não se reparou para

é um intervalo.

A classe pertence a um projeto meu e acho que é muito mais útil colocá-la toda já que já está pronta.
Mas sinta-se à vontade de cortar o que não lhe interessa, ou usar date/calendar a frio. Afinal, java é uma linguagem OO. Para quÊ vamos querer criar um classe , né ? :roll:

M

Não tem nada a ver com Calendar? tá certo então.
Desculpe-me…

:shock:

M

sergiotaborda:

Eu não acho nada. O problema não se resolve apenas usando Calendar , liás nada tem a haver com Calendar. Nem Date já agora. A classe é grande de mais ? é muito código ? Classes medem-se por metro agora ?

Tenho certeza que seu algoritmo é eficiente para o seu propósito. Mas querer passar como se fosse um trator pelo que eu disse parece mesquinhez.
Faça em Assembly então já que escrever código a toa em qualquer contexto é o que você prefere. Sugeri algo bem simples para ela trabalhar com as datas, nada mais.
Desculpe-me.

S

mfjeng:
Não tem nada a ver com Calendar? tá certo então.
Cara, só comentei uma pequena parte cidadão!

Não. Não tem nada a ver com calendar. O mesmo algoritmo pode funcionar para inteiros ou strings.
O ponto é que vc tem dois valores que mantêm um invervalo e tem dois intervalos. É o intervalo que pode ser intersectado com outro e não o dado que o mantém. Por isso o código que postei usa generics e comparator.
O que interessa realmente é que o objeto que dá suporte ao intervalo seja comparável.

Ficar comentando o tamanho de código tb…
Se vc ficou ofendido com o que eu disse deveria ter pensado antes no que vc disse.

A

Cara, da uma olhada na api JodaTime, bota no google que vem o site. Ela é a base da nova api de datas para o Java que está sendo construida. Bem legal e mais simples de trabalhar do que as apis padrões do JAVA. Acho que vai encontrar o que quer lá. E caso queria usar o hibernate por exemplo, para persistir, ela ja tem implementação para isso.

Alberto

S

Gostaria de agradecer todas as sugestões citadas nesse tópico.
Consegui resolver, espero que a lógica não esteja confusa. Aqui vai:

Lembrando que:
dataInicio1 e dataFim1 referem-se ao 1o. período
dataInicio2 e dataFim2 referem-se ao 2o. período

if ((dataFim2.compareTo(dataInicio1) >=0 && dataFim2.compareTo(dataFim1)<=0) || (dataInicio2.compareTo(dataInicio1) >=0 && dataInicio2.compareTo(dataFim1)<=0) || (dataInicio2.compareTo(dataInicio1) <= 0 && dataFim2.compareTo(dataFim1) >= 0) || (dataInicio2.compareTo(dataInicio1) >= 0 && dataFim2.compareTo(dataFim1) <= 0)) { //As datas se intercalam return false; }

Abraços… e mais uma vez muito obrigada!

Criado 19 de abril de 2008
Ultima resposta 22 de abr. de 2008
Respostas 11
Participantes 5