Groovy Scripted fields: working days / Hours when calculating dates

Daniela Scheiwe
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 16, 2013

Hi, I'm using a scripted field to calculate a latest start date based on due date and original estimation.

The problem I'm encountering is that the result date ignores Jiras settings for working days, hours per day etc. So when my task is due on monday 1pm and i have estimated 2 days for it, i want the latest start date to be set to thursday 1pm instead of sunday night, as 2 days are 16 hours.

Is there a function or simple script for that?

3 answers

1 vote
Tsol
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 22, 2013

Hey Daniella,

the following code if for a custom listener that catches the event of due date field editing and calculates the latest starting date according to the original estimate.

I have not used JiraDurationUtils cos i convert original estimate to working days in a different way.

I'm sure that the quality of code could be better but it works for my cases, also some imports are not necessary.

Hope it helps.

Cheers,

Kostas

import com.atlassian.jira.event.issue.AbstractIssueEventListener;
import com.atlassian.jira.event.issue.IssueEvent;
import com.atlassian.jira.event.issue.IssueEvent;
import com.atlassian.jira.event.type.EventDispatchOption;
import com.atlassian.jira.ComponentManager;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.comments.CommentManager;
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder;
import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.comments.CommentManager;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.security.JiraAuthenticationContext;
import com.atlassian.jira.user.ApplicationUser;
import com.atlassian.jira.util.JiraDurationUtils;
import com.atlassian.jira.util.I18nHelper;
import com.atlassian.crowd.embedded.api.User;
import java.sql.Connection;
import java.sql.Timestamp
import java.util.Locale;
import groovy.sql.Sql;
import org.apache.log4j.Category
import org.ofbiz.core.entity.ConnectionFactory;
import org.ofbiz.core.entity.DelegatorInterface;
import com.atlassian.jira.web.bean.I18nBean.AccessorFactory;
import com.atlassian.jira.util.I18nHelper;
import com.atlassian.jira.web.bean.I18nBean;







class UpdateDatesListener extends AbstractIssueEventListener {
    Category log = Category.getInstance(UpdateDatesListener.class)
    
 
    @Override
    void workflowEvent(IssueEvent event) {
	

	ComponentManager componentManager = ComponentManager.getInstance();
	
	MutableIssue issue = componentManager.getIssueManager().getIssueObject(event.getIssue().getLong("id"));


	
	if (issue.getDueDate()){

	//Condition, listener to be executed if duedate values changes. I should add here a condition when the original estimate changes

	if (event?.changeLog?.getRelated('ChildChangeItem')?.any{ it.field=='duedate' }) {
	//log.setLevel(org.apache.log4j.Level.DEBUG)
       log.warn "Event: ${event.getEventTypeId()} fired for ${event.issue} and caught by UpdateDatesListener"
	
	
	
	CustomFieldManager customFieldManager = ComponentManager.getInstance().getCustomFieldManager();
	
		
	IssueManager issueManager = componentManager.getIssueManager()

	User user = ComponentAccessor.getJiraAuthenticationContext().getUser().getDirectoryUser();
	

	
	
	//Create Custom Field Objects Using theis ids
	CustomField customField_planned_start = customFieldManager.getCustomFieldObject( 13602 );
	CustomField customField_planned_end = customFieldManager.getCustomFieldObject( 13603 );
	
	JiraDurationUtils jiraDurationUtils = ComponentAccessor.getComponent(JiraDurationUtils.class);
	
	
	
	//Get issue original estimate

	def original_est = issue.getOriginalEstimate() ?: 0


		
	//Get Due Date
	log.warn ("Due Date: " + issue.getDueDate());
	

	//Get the Original Estimate Original Value in Sec
	log.warn ("Original Work Estimate in secs: " + original_est);

	

	//Get the original estimate date in working days. If value is 3.4d, working days are rounded to 4d. 28800 are the seconds for 5d/8h working schedule.
	def working_days = Math.ceil((original_est/28800))

	log.warn ("Working Days: " + working_days.toInteger());


	//Calculate the range in weeks of original estimate
	def weeks = Math.ceil((working_days/5));
	
	//Print range
	log.warn ("Working Weeks: " + weeks);
	
	
	//Calculate extra days from weekends
	def extra_days;


	
	
	if (( issue.getDueDate().getDay() - working_days.toInteger() + (weeks.toInteger() - 1)*5 ) >= 0) {
	

	log.warn ("Residual: " + (issue.getDueDate().getDay() - working_days.toInteger() + (weeks.toInteger() - 1)*5))

	
	extra_days = (weeks - 1)*2;
	
	log.warn ("Extra Days: " + extra_days)
	
	} else {


	log.warn ("Residual: " + (issue.getDueDate().getDay() - working_days.toInteger() + (weeks.toInteger() - 1)*5))

	extra_days = weeks*2;

	

	log.warn ("Extra Days: " + extra_days)

	}


	//Set the new date time value in Planned Start customfield. The calcuation type is [issue.getDueDate() + 1 - (working_days.toInteger() + extra_days.toInteger())]
	
	issue.setCustomFieldValue(customField_planned_start, issue.getDueDate() + 1 - (working_days.toInteger() + extra_days.toInteger()));

	issueManager.updateIssue(user, issue, EventDispatchOption.ISSUE_UPDATED, false)

	}
	}
	}
	
}

1 vote
JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 21, 2013

Use com.atlassian.jira.util.JiraDurationUtils.

Tsol
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 21, 2013

Hey Jamie,

i'm trying to do exactly this thing but i haven't figured out how to do it.

I convert the absolute time of original estimate to working days but after that i do not know how to exlude the weekends.

I took a look in the API but i didn't find something that is doing that,

Thanx in advance.

Cheers,

Kostas

Tsol
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 21, 2013

Finally i have found a solution by converting the original estimate in number of weeks. That way i can exclude the weekends.

Daniela Scheiwe
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 22, 2013

Kostas, would you mind sharing your code?

THX

Daniela

0 votes
JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 22, 2013

eg:

def jiraDurationUtils = ComponentAccessor.getComponent(JiraDurationUtils.class)

assert "3 days" == jiraDurationUtils.getFormattedDuration(TimeUnit.HOURS.toSeconds(24))

You can get code to work out a duration ignoring weekends from stackoverflow.

This should be possible with jiraDurationUtils but I am not seeing it right now.

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events