How do I create a Customfield Searcher for a dateTime Customfield type (Time zone: UTC)?

Julia Janky August 23, 2023

Hello, 

I have created a custom field type that displays the date time in the UTC time zone with the following class:

import java.sql.Timestamp;

import java.util.Date;

import java.util.Map;

import java.util.TimeZone;

import org.apache.log4j.Logger;

import org.apache.commons.lang3.StringUtils;

import com.atlassian.jira.config.properties.APKeys;

import com.atlassian.jira.config.properties.ApplicationProperties;

import com.atlassian.jira.datetime.DateTimeFormatter;

import com.atlassian.jira.datetime.DateTimeFormatterFactory;

import com.atlassian.jira.datetime.DateTimeStyle;

import com.atlassian.jira.issue.Issue;

import com.atlassian.jira.issue.customfields.impl.DateTimeCFType;

import com.atlassian.jira.issue.customfields.impl.FieldValidationException;

import com.atlassian.jira.issue.customfields.impl.rest.DateTimeCustomFieldOperationsHandler;

import com.atlassian.jira.issue.customfields.manager.GenericConfigManager;

import com.atlassian.jira.issue.customfields.persistence.CustomFieldValuePersister;

import com.atlassian.jira.issue.fields.CustomField;

import com.atlassian.jira.issue.fields.OrderableField;

import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItem;

import com.atlassian.jira.issue.fields.rest.RestFieldOperationsHandler;

import com.atlassian.jira.issue.history.DateTimeFieldChangeLogHelper;

import com.atlassian.jira.issue.views.util.csv.CsvDateFormatter;

import com.atlassian.jira.security.JiraAuthenticationContext;

import com.atlassian.jira.util.I18nHelper;

import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;

import com.atlassian.plugin.spring.scanner.annotation.imports.JiraImport;



@Scanned

public class UTCDateTimeFieldType extends DateTimeCFType {


    DateTimeFormatter datePickerFormatter;


    JiraAuthenticationContext jiraAuthenticationContext;


    ApplicationProperties applicationProperties;


    public UTCDateTimeFieldType(

            @JiraImport CustomFieldValuePersister customFieldValuePersister,

            @JiraImport GenericConfigManager genericConfigManager,

            @JiraImport DateTimeFormatterFactory dateTimeFormatterFactory,

            @JiraImport JiraAuthenticationContext jiraAuthenticationContext,

            @JiraImport("jiraApplicationProperties") ApplicationProperties applicationProperties,

            @JiraImport DateTimeFieldChangeLogHelper dateTimeFieldChangeLogHelper,

            @JiraImport CsvDateFormatter csvDateFormatter) {

        super(customFieldValuePersister, genericConfigManager, dateTimeFormatterFactory, jiraAuthenticationContext, applicationProperties, dateTimeFieldChangeLogHelper, csvDateFormatter);

        this.datePickerFormatter = dateTimeFormatterFactory.formatter().withZone(TimeZone.getTimeZone("UTC")).withStyle(DateTimeStyle.DATE_TIME_PICKER);

        this.jiraAuthenticationContext = jiraAuthenticationContext;

        this.applicationProperties = applicationProperties;

    }


    final Logger logging = Logger.getLogger(UTCDateTimeFieldType.class);


    @Override

    public String getStringFromSingularObject(final Date customFieldObject) {

        return this.datePickerFormatter.format(customFieldObject);

    }


    @Override

    public Date getSingularObjectFromString(final String string) throws FieldValidationException {

        if (StringUtils.isEmpty(string)) {

            return null;

        }

        try {

            Date date = this.datePickerFormatter.parse(string);

            return new Timestamp(date.getTime());

        } catch (IllegalArgumentException e) {

            final I18nHelper i18nBean = jiraAuthenticationContext.getI18nHelper();

            throw new FieldValidationException(i18nBean.getText("fields.validation.data.format", applicationProperties.getDefaultBackedString(APKeys.JIRA_DATE_TIME_PICKER_JAVA_FORMAT)));

        }

    }


    @Override

    public String getNow() {

        return this.datePickerFormatter.format(new Date());

    }


    @Override

    public Map<String, Object> getVelocityParameters(final Issue issue, final CustomField field, final FieldLayoutItem fieldLayoutItem) {

        final Map<String, Object> map = super.getVelocityParameters(issue, field, fieldLayoutItem);

        map.put("dateTimePicker", Boolean.TRUE);

        map.put("datePickerFormatter", this.datePickerFormatter);

        map.put("titleFormatter", this.datePickerFormatter.withStyle(DateTimeStyle.COMPLETE));

        map.put("iso8601Formatter", this.datePickerFormatter.withStyle(DateTimeStyle.ISO_8601_DATE_TIME));

        return map;

    }


    @Override

    public RestFieldOperationsHandler getRestFieldOperation(CustomField field) {

        return new DateTimeCustomFieldOperationsHandler(field, this.datePickerFormatter, getI18nBean());

    }

}

The most important line for setting the time zone is this one:

this.datePickerFormatter = dateTimeFormatterFactory.formatter().withZone(TimeZone.getTimeZone("UTC")).withStyle(DateTimeStyle.DATE_TIME_PICKER);

Now, I want to create a custom field searcher. The default DateTimeRangeSearcher uses the time zone of the current user. 

Does anyone have an idea how to create a searcher that uses the UTC time zone?

Kind regards, 

Julia

1 answer

1 accepted

0 votes
Answer accepted
Julia Janky November 2, 2023

I found it out myself

Javier Portillo
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.
April 16, 2024

Could you please share the solution? Thanks in advance

Julia Janky April 16, 2024

Hello Javier Portillo,

sure. 

I created implementations of com.atlassian.jira.timezone.TimeZoneManager (UtcTimeZoneManagerImpl) and com.atlassian.jira.jql.util.JqlDateSupport (UtcJqlDateSupportImpl) where I replaced the time zones with the UTC time zone and the time zone manager with my implementation.

Then I created the searcher:

package com.scolution.jira.plugins.fields;

import com.atlassian.core.util.Clock;
import com.atlassian.jira.config.properties.ApplicationProperties;
import com.atlassian.jira.datetime.DateTimeFormatterFactory;
import com.atlassian.jira.issue.customfields.searchers.DateTimeRangeSearcher;
import com.atlassian.jira.issue.customfields.searchers.transformer.CustomFieldInputHelper;
import com.atlassian.jira.jql.operand.JqlOperandResolver;
import com.atlassian.jira.jql.util.JqlDateSupport;
import com.atlassian.jira.security.JiraAuthenticationContext;
import com.atlassian.jira.template.VelocityTemplatingEngine;
import com.atlassian.jira.timezone.TimeZoneManager;
import com.atlassian.jira.util.velocity.VelocityRequestContextFactory;
import com.atlassian.jira.web.action.util.CalendarLanguageUtil;
import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;
import com.atlassian.plugin.spring.scanner.annotation.imports.JiraImport;
import com.scolution.jira.plugins.fields.impl.UtcJqlDateSupportImpl;
import com.scolution.jira.plugins.fields.impl.UtcTimeZoneManagerImpl;

import javax.inject.Inject;

@Scanned
public class UtcDateTimeFieldSearcher extends DateTimeRangeSearcher {

@Inject
public UtcDateTimeFieldSearcher(
@JiraImport JiraAuthenticationContext context,
@JiraImport JqlOperandResolver jqlOperandResolver,
@JiraImport VelocityRequestContextFactory velocityRenderContext,
@JiraImport ApplicationProperties applicationProperties,
@JiraImport VelocityTemplatingEngine templatingEngine,
@JiraImport CalendarLanguageUtil calendarUtils,
@JiraImport JqlDateSupport dateSupport,
@JiraImport CustomFieldInputHelper customFieldInputHelper,
@JiraImport TimeZoneManager timeZoneManager,
@JiraImport DateTimeFormatterFactory dateTimeFormatterFactory,
@JiraImport Clock clock) {
super(context, jqlOperandResolver, velocityRenderContext, applicationProperties, templatingEngine, calendarUtils,
new UtcJqlDateSupportImpl(clock, new UtcTimeZoneManagerImpl()), customFieldInputHelper, new UtcTimeZoneManagerImpl(), dateTimeFormatterFactory);
}
}

The custom field searcher in the atlassian-plugin.xml:

<customfield-searcher key="utc-datetime-range-searcher" name="UTC Date Time Range Searcher"
class="com.scolution.jira.plugins.fields.UtcDateTimeFieldSearcher">
<description>Allow searching for a date and time that is between two other dates and times</description>
<valid-customfield-type package="${atlassian.plugin.key}" key="utc-date-time-field-type"/>
</customfield-searcher>

Kind regards,

Julia Janky 

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
SERVER
VERSION
9.7.1
TAGS
AUG Leaders

Atlassian Community Events