Groovy Scripted fields: working days / Hours when calculating dates

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

Use com.atlassian.jira.util.JiraDurationUtils.

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.



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

Kostas, would you mind sharing your code?



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.



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.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)
    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.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)



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
Community showcase
Published Feb 07, 2019 in Marketplace Apps

A Timeless Love Story

It started as any story starts, on a normal, rainy day.   Admin meets App, and her name was Klok2, and like any first relationship we were both trying to make it work but neither one knew what...

457 views 8 27
Read article

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you