All Downloads are FREE. Search and download functionalities are using the official Maven repository.

prerna.date.reactor.DateManipulationReactor Maven / Gradle / Ivy

The newest version!
package prerna.date.reactor;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import prerna.algorithm.api.SemossDataType;
import prerna.date.SemossDate;
import prerna.reactor.AbstractReactor;
import prerna.sablecc2.om.PixelDataType;
import prerna.sablecc2.om.execptions.SemossPixelException;
import prerna.sablecc2.om.nounmeta.NounMetadata;

public class DateManipulationReactor extends AbstractReactor {

	private static final String DEFAULT_FORMAT = "yyyy-MM-dd";

	// how to use
	// Frame() | Select( ...... ) | Filter (DATE_COLUMN_NAME >= DateManipulation("subtract", Date(), 7, "days") ) |
	// different flows 
	// DateManipulation("add", Date(), 7, "days")
	// DateManipulation("subtract", Date(), 7, "days")
	// DateManipulation("diff", Date("2020-11-01"), Date("2020-11-12"), "days")

	public DateManipulationReactor() {
		this.keysToGet = new String[] { "type", "date", "recurrence", "timeunit" };
	}

	@Override
	public NounMetadata execute() {
		organizeKeys();
		String type = this.keyValue.get(this.keysToGet[0]);
		if(type == null) {
			return NounMetadata.getErrorNounMessage("Must provide the 'type' of date manipulation");
		}
		return performManip(type);
	}

	private NounMetadata performManip(String type) {
		SemossDate startingDate = null;
		SemossDate compareDate = null;
		SemossDate dateToSendBack = null;
		String recurrence = "";
		String timeunit = "";
		int recurranceInt = 0;

		// get remaining keys
		if (this.keyValue.containsKey(this.keysToGet[1])) {
			String date = this.keyValue.get(this.keysToGet[1]);
			startingDate = new SemossDate(date, DEFAULT_FORMAT);
		}

		if (this.keyValue.containsKey(this.keysToGet[2])) {
			recurrence = this.keyValue.get(this.keysToGet[2]);
		} 

		if (this.keyValue.containsKey(this.keysToGet[3])) {
			timeunit = this.keyValue.get(this.keysToGet[3]);
		}
		
		if(startingDate == null) {
			throw new SemossPixelException("Starting Date must be set");
		}

		// based on the type of operation we will do the specific date manipulations here
		if (type.equalsIgnoreCase("add") || type.equalsIgnoreCase("addition")) {
			// integer check
			if (isInteger(recurrence)) {
				recurranceInt = Integer.parseInt(recurrence);
			}
			// get calendar object
			// perform manipulation
			// return a date
			Calendar c = Calendar.getInstance();
			c.setTime(startingDate.getDate());
			Date d = dateTimeAddition(c.getTime(), recurranceInt, timeunit);
			c.setTime(d);
			dateToSendBack = new SemossDate(c.getTime(), DEFAULT_FORMAT);
			return new NounMetadata(dateToSendBack, PixelDataType.CONST_DATE);

		} else if (type.equalsIgnoreCase("subtract") || type.equalsIgnoreCase("sub")
				|| type.equalsIgnoreCase("subtraction")) {
			// integer check
			if (isInteger(recurrence)) {
				recurranceInt = Integer.parseInt(recurrence);
			}
			Calendar c = Calendar.getInstance();
			c.setTime(startingDate.getDate());
			Date d = dateTimeAddition(c.getTime(), -recurranceInt, timeunit);
			c.setTime(d);
			dateToSendBack = new SemossDate(c.getTime(), DEFAULT_FORMAT);
			return new NounMetadata(dateToSendBack, PixelDataType.CONST_DATE);

		} else if (type.equalsIgnoreCase("diff") || type.equalsIgnoreCase("difference")) {
			compareDate = new SemossDate(recurrence, DEFAULT_FORMAT);
			Calendar c = Calendar.getInstance();
			c.setTime(startingDate.getDate());
			Calendar cLater = Calendar.getInstance();
			cLater.setTime(compareDate.getDate());
			long l = totalTimeUnitsBetween(c.getTime(),cLater.getTime(),timeunit);
			return new NounMetadata((int)l, PixelDataType.CONST_INT);
		}

		
		return NounMetadata.getErrorNounMessage("Unknown type = '" + type + "' for the date manipulation");
	}

	private boolean isInteger(String recurrence) {
		try {
			Integer.parseInt(recurrence);
			return true;
		} catch (Exception e) {
		}
		return false;
	}
	
	private Date dateTimeAddition(Date date1, int valToAdd, String timeUnit) {
		LocalDateTime localdatetime1 = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
		localdatetime1 = localdatetime1.plus(valToAdd, ChronoUnit.valueOf(timeUnit.toUpperCase()));
	    return Date.from(localdatetime1.atZone(ZoneId.systemDefault()).toInstant());
	}
	
	private long totalTimeUnitsBetween(Date dateBefore, Date dateAfter, String timeUnit) {
		try {
			LocalDate localdate1 = dateBefore.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
			LocalDate localdate2 = dateAfter.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
			return ChronoUnit.valueOf(timeUnit.toUpperCase()).between(localdate1, localdate2);
		} catch (Exception ex) { // for time units smaller than days time-units
			long diffInMillies = dateAfter.getTime() - dateBefore.getTime();
			return TimeUnit.valueOf(timeUnit.toUpperCase()).convert(diffInMillies, TimeUnit.MILLISECONDS);
		}
	}
	
	private SemossDataType determineReturnOutput() {
		organizeKeys();
		String type = this.keyValue.get(this.keysToGet[0]);
		if(type == null) {
			throw new IllegalArgumentException("Must provide the 'type' of date manipulation");
		}
		
		if (type.equalsIgnoreCase("add") || type.equalsIgnoreCase("addition")
				|| type.equalsIgnoreCase("subtract") || type.equalsIgnoreCase("sub")
						|| type.equalsIgnoreCase("subtraction")) {
			return SemossDataType.DATE;
		} else if (type.equalsIgnoreCase("diff") || type.equalsIgnoreCase("difference")) {
			return SemossDataType.INT;
		}
		
		throw new IllegalArgumentException("Unknown type = '" + type + "' for the date manipulation");
	}
	
	@Override
	public boolean canMergeIntoQs() {
		return true;
	}
	
	@Override
	public Map mergeIntoQsMetadata() {
		Map qsMergeMetadata = new HashMap<>();
		qsMergeMetadata.put(MERGE_INTO_QS_FORMAT, MERGE_INTO_QS_FORMAT_SCALAR);
		qsMergeMetadata.put(MERGE_INTO_QS_DATATYPE, determineReturnOutput() );
		return qsMergeMetadata;
	}
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy