Add months to a date in groovy - datetime

I am trying to add dynamic number of months to a date using groovy. I have tried it using TimeCategory.
I have tried as mentioned in the blog here -
[https://stackoverflow.com/questions/31707460/how-to-add-year-or-months-from-current-date-in-groovy]
However my below code dosent return correct output.
Need help to figure out what's wrong with my code.
My Input - CurrentRunDate = 2022-09-19, additionalmonths = 5
Current output from above code - MM/dd/yyyy5 months
import com.sap.it.api.mapping.*;
import java.text.SimpleDateFormat;
import groovy.time.TimeCategory
def String AddMonthsToDate(String CurrentRunDate, int additionalmonths){
def emptydate = "";
if(CurrentRunDate == "")
{
return emptydate;
}
else
{
use(TimeCategory) {
def currentdate = CurrentRunDate.format("MM/dd/yyyy")
def addmonths = currentdate + additionalmonths.month
return addmonths
}
}}

The issue here is that you are not converting CurrentRunDate into a Date object before using it with TimeCategory. You need to parse the date string, add the months you want, and then convert the Date back into a String to return.
In essence, you'll want something similar to this:
import java.text.SimpleDateFormat
import groovy.time.TimeCategory
String addMonthsToDate(String currentRunDate, int additionalMonths) {
// validate currentRunDate as being present and truthy
if (!currentRunDate) {
return ""
}
// lets set up our simple date format object for parsing and formating
def sdf = new SimpleDateFormat("MM/dd/yyyy")
// using that formmater let's parse the date string into a date obj
def parsedDate = sdf.parse(currentRunDate)
// let's now use that date obj in the TimeCategory body
def datePlusOneMonth = use(TimeCategory) { parsedDate + additionalMonths.month }
// let's convert back to a string
return sdf.format(datePlusOneMonth)
}
As a test:
assert addMonthsToDate("01/01/2000", 1) == "02/01/2000"

Related

Database DateTime milli and nano seconds are truncated by default if they are 0s, while using it in Java 11 using ZonedDateTime

I am fetching datetime from an Oracle database and parsing in Java 11 using ZonedDateTime as below:
Oracle --> 1/19/2020 06:09:46.038631 PM
Java ZonedDateTime output --> 2020-01-19T18:09:46.038631Z[UTC]
Oracle --> 1/19/2011 4:00:00.000000 AM
Java ZonedDateTime output --> 2011-01-19T04:00Z[UTC] (So, here the 0s are truncated by default.
However, my requirement is to have consistent fixed length output like #1.)
Expected Java ZonedDateTime output --> 2011-01-19T04:00:00.000000Z[UTC]
However, I didn’t find any date API methods to achieve above expected output. Instead of manipulating a string, is there a way to preserve the trailing 0s with fixed length?
We have consistent ZonedDateTime types in the application, so we do not prefer to change that.
We have consistent ZonedDateTime type in application, so we do not
prefer to change that.
Why do you think 2011-01-19T04:00Z[UTC] is inconsistent? A date-time object is supposed to hold (and provide methods/functions to operate with) only the date, time, and time-zone information. It is not supposed to store any formatting information; otherwise, it will violate the Single-responsibility principle. The formatting should be handled by a formating class e.g. DateTimeFormatter (for modern date-time API), DateFormat (for legacy java.util date-time API) etc.
Every class is supposed to override the toString() function; otherwise, Object#toString will be returned when its object will be printed. A ZonedDateTime has date, time and time-zone information. Given below is how its toString() for time-part has been implemented:
#Override
public String toString() {
StringBuilder buf = new StringBuilder(18);
int hourValue = hour;
int minuteValue = minute;
int secondValue = second;
int nanoValue = nano;
buf.append(hourValue < 10 ? "0" : "").append(hourValue)
.append(minuteValue < 10 ? ":0" : ":").append(minuteValue);
if (secondValue > 0 || nanoValue > 0) {
buf.append(secondValue < 10 ? ":0" : ":").append(secondValue);
if (nanoValue > 0) {
buf.append('.');
if (nanoValue % 1000_000 == 0) {
buf.append(Integer.toString((nanoValue / 1000_000) + 1000).substring(1));
} else if (nanoValue % 1000 == 0) {
buf.append(Integer.toString((nanoValue / 1000) + 1000_000).substring(1));
} else {
buf.append(Integer.toString((nanoValue) + 1000_000_000).substring(1));
}
}
}
return buf.toString();
}
As you can see, the second and nano parts are included in the returned string only when they are greater than 0. It means that you need to use a formatting class if you want these (second and nano) zeros in the output string. Given below is an example:
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String input = "1/19/2011 4:00:00.000000 AM";
// Formatter for input string
DateTimeFormatter inputFormatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("M/d/u H:m:s.n a")
.toFormatter(Locale.ENGLISH);
ZonedDateTime zdt = LocalDateTime.parse(input, inputFormatter).atZone(ZoneOffset.UTC);
// Print `zdt` in default format i.e. the string returned by `zdt.toString()`
System.out.println(zdt);
// Formatter for input string
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.nnnnnnz");
String output = zdt.format(outputFormatter);
System.out.println(output);
}
}
Output:
2011-01-19T04:00Z
2011-01-19T04:00:00.000000Z
Food for thought:
public class Main {
public static void main(String[] args) {
double d = 5.0000;
System.out.println(d);
}
}
What output do you expect from the code given above? Does 5.0 represent a value different from 5.0000? How will you print 5.0000? [Hint: Check String#format, NumberFormat, BigDecimal etc.]

Java 8 Time API: how to parse string of format “mm:ss” to Duration?

I tried to use DateTimeFormatter for it, but not found way.
Duration.parse("") only use special format.
You can parse the String yourself and reformat it into the format required by Duration
String value = ... //mm:ss
String[] fields = value.split(":");
return Duration.parse(String.format("P%dM%sS", fields[0], fields[1]));
The accepted answer guides in the right direction but it has the following problems which may be difficult for a beginner to figure out and correct:
It does not follow the correct format of Duration which starts with PT.
It should use %s instead of %d for fields[0] as fields[0] is of type, String.
After correcting these two things, the return statement will become
return Duration.parse(String.format("PT%sM%sS", fields[0], fields[1]));
An alternative to splitting and formatting can be to use String#replaceAll as shown below:
import java.time.Duration;
public class Main {
public static void main(String[] args) {
// Test
System.out.println(parseToDuration("09:34"));
System.out.println(parseToDuration("90:34"));
System.out.println(parseToDuration("9:34"));
System.out.println(parseToDuration("0:34"));
System.out.println(parseToDuration("00:04"));
System.out.println(parseToDuration("1:2"));
}
static Duration parseToDuration(String value) {
return Duration.parse(value.replaceAll("(\\d{1,2}):(\\d{1,2})", "PT$1M$2S"));
}
}
Output:
PT9M34S
PT1H30M34S
PT9M34S
PT34S
PT4S
PT1M2S
The regex, (\d{1,2}):(\d{1,2}) has two capturing groups: group(1) is specified with $1 and group(2) is specified with $2 in the replacement string. Each capturing group has \d{1,2} which specifies 1 to 2 digit(s).
IMHO, java 8 doesn't provide any facility for custom duration parsing.
You should to do it "manually". For example (an efficient way) :
import static java.lang.Integer.valueOf;
import java.time.Duration;
public class DurationParser {
public static Duration parse(String input) {
int colonIndex = input.indexOf(':');
String mm = input.substring(0, colonIndex);
String ss = input.substring(colonIndex + 1);
return Duration.ofMinutes(valueOf(mm)).plusSeconds(valueOf(ss));
}
}

javafx: how to check if a date is greater than today's date?

If I have:
DatePicker dp = new DataPicker();
and at some point I want to know if the data is greater than today, how can I do it?
Example:
if I want to book a room in a hotel from 21/04/2014 well, it should be impossible because today is 28/07/2014.
How can I do it in JavaFX ?
To ensure that a given Date chosenDate is after today, you can check
if (chosenDate.after(new Date())) {
// valid (Date > today)
} else {
// invalid (Date <= today)
}
Note that chosenDate should be a Date with hour, minute and second set to 0 since else it could accept a Date with the same day as today but a later hour than now.
You can write a custom method, which will compare given dates of given date format, and return true, when current date is "older" than your date of interest, eg:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Demo {
public static void main(String args[]) {
System.out.println(isDateOfInterestValid("yyyy-mm-dd",
"2014-08-25", "2014-08-28"));
}
public static boolean isDateOfInterestValid(String dateformat,
String currentDate, String dateOfInterest) {
String format = dateformat;
SimpleDateFormat sdf = new SimpleDateFormat(format);
Date cd = null; // current date
Date doi = null; // date of interest
try {
cd = sdf.parse(currentDate);
doi = sdf.parse(dateOfInterest);
} catch (ParseException e) {
e.printStackTrace();
}
long diff = cd.getTime() - doi.getTime();
int diffDays = (int) (diff / (24 * 1000 * 60 * 60));
if (diffDays > 0) {
return false;
} else {
return true;
}
}
}
And in context of pure JavaFX you can get the String value of DatePicker chosen date by calling DatePicker.getValue().toString().
PS In case You have only one DatePicker object, You can use "hidden" method, which will check the current date. It can look like this:
public static String currentDate(String separator) {
Calendar date = new GregorianCalendar();
String day = Integer.toString(date.get(Calendar.DAY_OF_MONTH));
String month = Integer.toString(date.get(Calendar.MONTH) + 1);
String year = Integer.toString(date.get(Calendar.YEAR));
if (month.length() < 2) {
month = "0" + month;
}
if (day.length() < 2) {
day = "0" + day;
}
String regDate = year + separator + month + separator + day;
return regDate;
}

How do I parse JSON dates with ActionScript?

I have dates in JSON which are generated from ASP.NET pages using the JSON.NET library. These dates look like this:
"LastModifiedDate": "\/Date(1301412877000-0400)\/"
How do I parse these with ActionScript from Flex 3 Professional? I'd like to have this in a native data format.
NOTE: What I'm not asking here is how do I parse a JSON feed with as3corelib. I have the JSON deserialized with that library but the dates are not decoded. That is why I need to know how to decode this date format.
You'll want to use as3corelib's JSON implementation to decode your string into Objects.
/**
* Converts 'Unix tick' format JSON Date to AS3 Date instances.
* Example json input: "{\"BarDate\":\"\/Date(1334672700000)\/\" }"
* Example json input: "{\"BarDate\":\"\/Date(1334672700000+0000)\/\" }"
*
* #param json date from JSON
* #return Date if conversion possible and worked else null.
*/
public static function parseJSONUnixTickDateToDate(json:String):Date
{
var date:Date = null;
if (json)
{
json = json.substring(json.indexOf("(") + 1, json.indexOf(")"));
var arr:Array = json.split("+");
date = new Date(Number(arr[0]));
}
return date;
}
In ASP I use this function to get a Json date
public static double JsonTime(DateTime dt)
{//Convert datetime to a Json Datetime
DateTime d1 = new DateTime(1970, 1, 1);
DateTime d2 = dt.ToUniversalTime();
TimeSpan ts = new TimeSpan(d2.Ticks - d1.Ticks);
return Math.Round( ts.TotalMilliseconds,0);
}
and then in JavaScript I use:
if (data.indexOf("\/Date(")==7)
return new Date(+data.replace(/\D/g, ''));
to convert back to a date if that helps
You will also have fun with single and double quotes but for the life of me I can not find a decoder that works server side with Json strings on Net Framework 3!
if you use String ="\u0027" in your code then the string is already converted and in the end I wrote a function that about does the job using a loop.
string Padding = "000";
for (int f = 1; f <= 256; f++)
{
string Hex = "\\u" + Padding.Substring(0, 4 - f.ToString().Length) + f;
string Dec = "&#" + Int32.Parse(f.ToString(), NumberStyles.HexNumber) + ";";
HTML = HTML.Replace(Hex, Dec);
}
HTML = System.Web.HttpUtility.HtmlDecode(HTML);
Bad I know but if you have a better answer then please let me know!

How to work with several fields in DateTime?

public DateTime EnterDeparture()
{
Console.WriteLine("Enter Year:");
return new DateTime().AddYears(int.Parse(Console.ReadLine()));
}
// This will return new DateTime(Without assigned Year) Cause DateTime is value type.
public DateTime EnterDeparture()
{
DateTime EnterDeparture = new DateTime();
Console.WriteLine("Enter Year:");
EnterDeparture.AddYears(int.Parse(Console.ReadLine()));
return EnterDeparture;
}
How to work with several fields in DateTime ? (Year,Days for example) Default constructors aren't suitable.
The DateTime.AddXXX methods return new DateTime instances, the existing struct does not change. Since each method returns a new instance, you can chain the method calls together. At the very least, you want to capture each return value into a variable. For example:
DateTime myDate = DateTime.Today;
DateTime tomorrowAtNoon = myDate.AddDays(1).AddHours(12);
You could have also written it like
DateTime tomorrow = myDate.AddDays(1);
DateTime tomorrowAtNoon = tomorrow.AddHours(12);
Follow?

Resources