Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Creating a Custom JQL Function for Quarters in Jira Data Center Using ScriptRunner

David Shahbazyan
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 Champions.
June 25, 2026

 

Hi everyone!

I created a custom JQL function in Jira Data Center using ScriptRunner.

The function allows users to search issues by the quarter in which they were created.

Example:

 

issueFunction in createdQuarter(1)

This returns issues created in the first quarter of the current year.

The function uses the current year automatically and converts the selected quarter into the correct created date range.

This function is especially useful for dashboards that show quarterly data. Since it automatically uses the current year, there is no need to manually update the JQL date ranges every year.


Script

package com.onresolve.jira.groovy.jql

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.jql.query.LuceneQueryBuilder
import com.atlassian.jira.jql.query.QueryCreationContext
import com.atlassian.jira.jql.validator.NumberOfArgumentsValidator
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.util.MessageSet
import com.atlassian.query.clause.TerminalClause
import com.atlassian.query.operand.FunctionOperand
import org.apache.lucene.search.Query

import java.time.LocalDate

class CreatedQuarter extends AbstractScriptedJqlFunction implements JqlQueryFunction {

JqlQueryParser queryParser = ComponentAccessor.getComponent(JqlQueryParser)
LuceneQueryBuilder luceneQueryBuilder = ComponentAccessor.getComponent(LuceneQueryBuilder)

@Override
String getDescription() {
"Returns issues created in the selected quarter of the current year. Example: issueFunction in createdQuarter(1)"
}

@Override
List<Map> getArguments() {
[
[
description: "Quarter number: 1, 2, 3, or 4",
optional : false,
]
]
}

@Override
String getFunctionName() {
"createdQuarter"
}

@Override
MessageSet validate(ApplicationUser user, FunctionOperand operand, TerminalClause terminalClause) {
def messageSet = new NumberOfArgumentsValidator(1, 1, getI18n()).validate(operand)

if (messageSet.hasAnyErrors()) {
return messageSet
}

def quarterText = operand.args.first()

if (!(quarterText ==~ /[1-4]/)) {
messageSet.addErrorMessage(
"createdQuarter() accepts only 1, 2, 3, or 4. Example: issueFunction in createdQuarter(1)"
)
return messageSet
}

def query = buildJiraQuery(quarterText as Integer)
searchService.validateQuery(user, query)
}

@Override
Query getQuery(QueryCreationContext queryCreationContext, FunctionOperand operand, TerminalClause terminalClause) {
def quarter = operand.args.first() as Integer
def query = buildJiraQuery(quarter)

luceneQueryBuilder.createLuceneQuery(queryCreationContext, query.whereClause)
}

private com.atlassian.query.Query buildJiraQuery(Integer quarter) {
int year = LocalDate.now().year

LocalDate startDate
LocalDate endDate

switch (quarter) {
case 1:
startDate = LocalDate.of(year, 1, 1)
endDate = LocalDate.of(year, 4, 1)
break
case 2:
startDate = LocalDate.of(year, 4, 1)
endDate = LocalDate.of(year, 7, 1)
break
case 3:
startDate = LocalDate.of(year, 7, 1)
endDate = LocalDate.of(year, 10, 1)
break
case 4:
startDate = LocalDate.of(year, 10, 1)
endDate = LocalDate.of(year + 1, 1, 1)
break
default:
throw new IllegalArgumentException("Quarter must be 1, 2, 3, or 4")
}

def jql = "created >= '${startDate}' AND created < '${endDate}'"
queryParser.parseQuery(jql)
}
}

 

1 answer

Suggest an answer

Log in or Sign up to answer
0 votes
Martin Runge
Community Champion
July 2, 2026

Hi @David Shahbazyan

Thanks so much for sharing this! I really like it and have bookmarked it because it might come in handy down the line. You’re running this on Jira 11 with the Lucene backend, correct?

Are you thinking about using Adaptavist's latest custom JQL function example for ScriptRunner 10.x and above, which now uses com.atlassian.jira.search.Query and DefaultQueryFactory instead, to avoid depending directly on Lucene?

Cheers,
Martin

David Shahbazyan
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 Champions.
July 6, 2026

Dear @Martin Runge , thanks a lot!

Yes, I think it wolud be effective.

TAGS
AUG Leaders

Atlassian Community Events