Calculate age in Groovy from today - groovy

Trying to figure out how old someone is based on their bday. The following code gives us the number of days
def now = new Date()
def dob = new Date('08/21/1982')
println now - dob
We could divide by 365 but that isn't entirely accurate. There has to be an easy way to do this but I just can't seem to find it. Any ideas?

Or using Java 8 and Groovy 2.3 RC (if you want to be on the bleeding edge) ;-)
import java.time.*
LocalDate today = LocalDate.now()
LocalDate birthday = LocalDate.of( 1982, Month.AUGUST, 8 )
Period period = Period.between( birthday, today )
println """$period.years years,
|$period.months months,
|$period.days days""".stripMargin()

Here is a sleek alternative using joda time :)
#Grab('joda-time:joda-time:2.3')
import org.joda.time.Period
import org.joda.time.DateTime
def now = new DateTime()
def dob = new DateTime(1982, 8, 21, 0, 0)
def period = new Period(dob, now)
println """$period.years years,
|$period.months months,
|$period.days days,
|$period.hours hours,
|$period.minutes minutes
""".stripMargin()

For me joda was not available so I searched another, more groovy solution and found:
def duration = groovy.time.TimeCategory.minus(
new Date(),//date1
new Date(session.creationTime)//date2
);
println "seconds: " + dur2.seconds;
println "min: " + dur2.minutes;
println "hours: " + dur2.hours;

import com.sap.it.api.mapping.*;
import java.util.HashMap;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Calendar;
import java.util.TimeZone;
import groovy.time.TimeCategory;
import groovy.time.TimeDuration;
def String customFunc(String DOB){
if(DOB == '')
{
DOB = '';
return DOB;
}
else
{
Date birth_yr=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").parse(DOB);
Date date = new Date();
def duration = groovy.time.TimeCategory.minus(date,birth_yr);
def age = (duration.days).intdiv(365)
return age
}
}

Related

Copy date from one field to another

I am trying to copy the value of one date field to another. But, the field is not getting set. When I hardcode the date value it works.
Original field is Scheduled Start Time and the field I am trying to copy the value to is: Planned Scheduled Start Time. These are both date type fields.
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.config.properties.APKeys
import com.atlassian.jira.datetime.DateTimeFormatter as JiraDateTimeFormatter
import com.atlassian.jira.issue.customfields.impl.DateTimeCFType
import com.atlassian.jira.issue.fields.CustomField
import com.onresolve.jira.groovy.user.FieldBehaviours
import groovy.transform.BaseScript
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.temporal.TemporalAccessor
import java.time.format.DateTimeFormatter
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.user.util.UserUtil
import java.util.Date.*
#BaseScript FieldBehaviours fieldBehaviours
// The date & date time field names to set a value
final plannedScheduledStart = "Planned Scheduled Start Time"
final plannedScheduledCompletion = "Planned Scheduled Completion Time"
final scheduledStart = "Scheduled Start Time"
final scheduledCompletion = "Scheduled Completion Time"
// Get the components
def customFieldManager = ComponentAccessor.customFieldManager
def authenticationContext = ComponentAccessor.jiraAuthenticationContext
// Get the date & date time field objects
//def dateFieldStart = customFieldManager.getCustomFieldObjectsByName(plannedScheduledStart).first()
def dateFieldStart = getFieldByName("Planned Scheduled Start Time")
def dateFieldCompletion = customFieldManager.getCustomFieldObjectsByName(plannedScheduledCompletion).first()
def dateScheduledStart = customFieldManager.getCustomFieldObjectsByName(scheduledStart).first()
def dateScheduledCompletion = customFieldManager.getCustomFieldObjectsByName(scheduledCompletion).first()
def dataValue = dateFieldStart.getValue().toString()
getFieldByName("Scheduled Start Time").setFormValue(dataValue)
I also tried def dataValue = dateFieldStart.getValue() and it failed

Block Jira opening ticket if custom field value is less than 1 using Groovy

i need to block the creation of an issue on Jira if a custom field value is less than 1.
I tried with this code with no success, the custom field ID is: 13200.
import com.atlassian.jira.component.ComponentAccessor;
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.opensymphony.workflow.InvalidInputException;
import org.apache.log4j.Category;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue;
import groovy.xml.MarkupBuilder;
import com.atlassian.jira.config.properties.APKeys;
def issueManager = ComponentAccessor.getIssueManager()
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def cField = customFieldManager.getCustomFieldObject("customfield_13200")
def cFieldValue = issue.getCustomFieldValue(cField) as Integer
if (cFieldValue > 0){
log.debug("ERRORE, QUANTITA' NON DISPONIBILI");
throw "ERRORE";
throw new InvalidInputException("QUANTITA' NON DISPONIBILI");
return cFieldValue;
return false;
}
That custom field is taken from another DB (linked via Elements) and it's the quantity of a particular item, if the quantity is less than 0 the ticket should throw an exception but it doesnt work as i would, giving me this error in the LOG:
For input string: "{"keys":["47"]}"
java.lang.NumberFormatException: For input string: "{"keys":["47"]}"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.valueOf(Integer.java:766)
The taken value is right (47) but maybe it's in a wrong type?
Can anybody help me?
Thank you,
Luca
Your variable content is "{"keys":["47"]}" , not "47". You can see this here: java.lang.NumberFormatException: For input string: "{"keys":["47"]}"
that's why you get this exception, as "{"keys":["47"]}" cannot be converted to a number, so please double-check the value of the variable you are converting to a number
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.component.ComponentAccessor
import com.opensymphony.workflow.InvalidInputException
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def Scorte = customFieldManager.getCustomFieldObject("customfield_13200")
def ValoreScorte = issueObject.getCustomFieldValue(Scorte)
def QuantitaRichiesta = customFieldManager.getCustomFieldObject("customfield_13201")
def ValoreQuantitaRichiesta = issueObject.getCustomFieldValue(QuantitaRichiesta)
def casting_ValoreScorte = ValoreScorte.toString().replaceAll("[^\\d.]", "")
def Scorte_Intero = casting_ValoreScorte as int
def QuantitaRichiesta_Intero = ValoreQuantitaRichiesta as int
if (Scorte_Intero <= 0 || QuantitaRichiesta_Intero > Scorte_Intero){
log.debug("ERRORE, QUANTITA' NON DISPONIBILI")
throw new InvalidInputException("","QUANTITA' NON DISPONIBILI")
}
This is the final code :) Thank you for your help!

extract multiple URLs using the datetime function

In this program i am not using request or beautiful soup function. I'm instead only using the datetime to extract the URLs. Now in the current program, I have written to extract the values for a long period. I want to make it in such a way that, if I automate this program and it runs today, it will extract yesterday's data. Similarly if it runs tomorrow, it will extract todays data and so on.
here is the code,
import datetime
from datetime import date, datetime,timedelta
import warnings
import datetime
import pandas as pd
import wget
import glob
import os
warnings.filterwarnings("ignore")
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
from urllib.error import HTTPError
def date_range(start_date,end_date):
for n in range(int((end_date-start_date).days)):
yield start_date + timedelta(n)
def get_urls(base_url):
part_two = "/dailyCoal1-"
end_part = ".xlsx"
start_date = date(2020,11,1)
end_date = datetime.datetime.now().date()
start_urls = list()
for single_date in date_range(start_date, end_date):
start_urls.append(single_date.strftime(base_url+'%d-%m-%Y'+part_two+'%Y-%m-%d'+end_part))
return start_urls
def excel_download(link,out):
#downloads a given link provided to a output directory in out
wget.download(link,out)
if __name__ =="__main__":
base_url = "https://npp.gov.in/public-reports/cea/daily/fuel/"
mypath = "/Users/vp/Desktop/temp"
temp_folder = '/Users/vp/Desktop/temp'
out_folder = "/Users/vp/Desktop/NPP"
log_file = os.path.join(out_folder,'debug_log_npp.log')
out_file = os.path.join(out_folder,'Energy_inputs_npp.csv')
file_links = get_urls(base_url)
for link in file_links:
try:
excel_download(link,temp_folder)
except HTTPError:
content = "HTTP issue while capturing data for this link - " + link
log_writer(log_file,content)
continue
file = glob.glob(os.path.join(temp_folder,'*.xlsx'),recursive=True)[0]
df = pd.read_excel(file)
To capture yesterday's data, i created this in the main function where i check for yesterday = and then cancel if it isnt yesterday. But then its throwing error as it constantly picks the start date as its day one.
if(date_time_obj != Yesterday):
os.remove(file)
content = "Date mis-matched - " + str(date_time_obj) + " " + str(Yesterday)
In this program, date_time_obj - is the date it is currently trying to extract data for.
Everyday if this program runs at 8pm, it needs to only capture one day before data on a daily basis.
if this cannot be done in datetime, but only on request or bs4, then how do i approach this problem?
I don't know if you wanted a valid link as your code doesn't seem to produce those for me but you only need to tweak to work off start_date only and return a single item to return yesterday's link matching with your current output for same date.
import datetime
from datetime import date, datetime,timedelta
import warnings
import datetime
import pandas as pd
import glob
import os
warnings.filterwarnings("ignore")
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
from urllib.error import HTTPError
def get_url(base_url):
part_two = "/dailyCoal1-"
end_part = ".xlsx"
start_date = datetime.datetime.now().date() + timedelta(-1)
start_url = start_date.strftime(base_url+'%d-%m-%Y'+part_two+'%Y-%m-%d'+end_part)
return start_url
def excel_download(link,out):
#downloads a given link provided to a output directory in out
wget.download(link,out)
if __name__ =="__main__":
base_url = "https://npp.gov.in/public-reports/cea/daily/fuel/"
mypath = "/Users/vp/Desktop/temp"
temp_folder = '/Users/vp/Desktop/temp'
out_folder = "/Users/vp/Desktop/NPP"
log_file = os.path.join(out_folder,'debug_log_npp.log')
out_file = os.path.join(out_folder,'Energy_inputs_npp.csv')
file_link = get_url(base_url)
print(file_link)

Datetime Module, Time

I'm trying to print the actual time on an hourly based automated Email, but the program is repeating the first printed time again again. For Example, if the first rounds starts at 6:00 AM cst,again in the next email it is printing the same instead of 7:00, where I'm going wrong with the code below
import pytz
from datetime import datetime
import time
utc = timezone('UTC')
central = pytz.timezone('US/Central')
today = datetime.now(central)
crntDte = today.strftime("%m/%d/%Y")
crntTime = datetime.now(central).strftime('%H:%M')
def Action():
print('Process started at '+ crntDte + " " + crntTime)
schedule.every(2).minutes.do(Action)
while True:
schedule.run_pending()
time.sleep(1)
crntDte is working fine, but crnTime is printing the sametime everyhour
Well, your timezone looks not properly set. There are two timezone that are from pytz and datetime. I think you have to specify which one you will use.
import pytz
from datetime import datetime
import time
central = pytz.timezone('US/Central')
today = datetime.now(central)
crntDte = today.strftime("%m/%d/%Y")
crntTime = today.strftime('%H:%M')
print('Process started at '+ crntDte + " " + crntTime)
The result is then (for now)
Process started at 10/19/2019 09:18
When you do some schedule, then you have to re-calculate the time. So, your action should have all the definitions not only the print statement.
import pytz
from datetime import datetime
import time
def Action():
central = pytz.timezone('US/Central')
today = datetime.now(central)
crntDte = today.strftime("%m/%d/%Y")
crntTime = today.strftime('%H:%M')
print('Process started at '+ crntDte + " " + crntTime)
schedule.every(2).minutes.do(Action)
while True:
schedule.run_pending()
time.sleep(1)
There are not updated automatically.

Sqlalchemy filter by calculated datetime hybrid_property

I have a model Prescription.
from datetime import timedelta
from sqlalchemy.ext.hybrid import hybrid_property
class Prescription(db.Model):
""" docstring """
ID = db.column(db.Integer, primary_key=True)
date = db.Column(db.DateTime)
duration = db.Column(db.SmallInteger)
#hybrid_property
def expiration_date(self):
# return self.date + timedelta(days=self.duration)
return self.date + timedelta(days=7)
#classmethod
def actual(cls ):
""" docstring """
today = datetime.today()
return cls.query.filter(Prescription.expiration_date>=today)
I want to get only actual prescriptions in my actual method, and when I specify
#hybrid_property
def expiration_date(self):
return self.date + timedelta(days=7)
everything works like a charm.
But every prescription has a different duration, and when I specify
#hybrid_property
def expiration_date(self):
return self.date + timedelta(days=self.duration)
I've got an error
TypeError: unsupported type for timedelta days component: InstrumentedAttribute
I tried to make a little hack like this
#property
def days(self):
return int(self.duration)
but no luck.
Can anyone tell some workaround, or creating some lazy object for duration field or maybe another way get actual prescriptions, filtering by calculated expiration_date?
You might be trying to calculate a DATEDIFF:
Calculate DATEDIFF in POSTGRES using SQLAlchemy
Here, is_expired will generate a SQL query part which calculates difference in days between the start date and utcnow(), and compares the result with self.duration
This works in PostgreSQL, but I have not tested on other RDBMS.
from datetime import datetime
import sqlalchemy as sa
class Prescription:
ID = db.column(db.Integer, primary_key=True)
date = db.Column(db.DateTime)
duration = db.Column(db.SmallInteger)
#hybrid_property
def is_expired(self):
days_since_published = sa.func.trunc((
sa.extract('epoch', datetime.utcnow()) -
sa.extract('epoch', self.date)
) / 3600 / 24)
return days_since_published >= self.duration
#classmethod
def active(cls):
return cls.query.filter(is_expired=False)
In your #classmethod annotated actual() method, you are trying to access a non-static property(expiration_date) which is raising the error.
As per my understanding of what your code is doing, I have changed the code as follow:
from datetime import datetime,timedelta
from sqlalchemy.ext.hybrid import hybrid_property
from flask_sqlalchemy import SQLAlchemy
from flask import Flask
app = Flask(__name__)
db = SQLAlchemy(app)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:///'
class Prescription(db.Model):
""" docstring """
def mydefault(context):
return context.get_current_parameters()['date'] + timedelta(days=context.get_current_parameters()['duration'])
ID = db.Column(db.Integer,primary_key= True)
date = db.Column(db.Date)
duration = db.Column(db.SmallInteger)
expiration_date = db.Column(db.Date,default = mydefault)
#classmethod
def actual(cls ):
""" docstring """
today = datetime.today().date()
return cls.query.filter(Prescription.expiration_date>=today).all()
def __repr__(self):
return "Id:{} , date:{}, duration:{}, expiration_date:{}".format(self.ID,self.date,self.duration,self.expiration_date)
db.create_all()
q=Prescription(ID=1,date=datetime(2019,5,26).date(),duration = 1) #Expired
r=Prescription(ID=2,date=datetime(2019,5,20).date(),duration = 3) #Expired
s=Prescription(ID=3,date=datetime(2019,5,27).date(),duration = 5) #Not Expired
t = Prescription(ID=4,date=datetime.now().date(),duration = 1) #Not Expired
db.session.add(q)
db.session.add(r)
db.session.add(s)
db.session.add(t)
db.session.commit()
list_obj = Prescription.query.all()
print("All Objects in DB:-")
for l in list_obj:
print(l)
print()
print("Valid Prescription:")
print(Prescription.actual())
Output:
One thing I can suggest to you is since the model does not need the time of expiration.
So you could change
date = db.Column(db.DateTime)
to
date = db.Column(db.Date)
and it will ease your task :)

Resources