I'm create a java webapp and I have to create a consecutive number that should starts every month. The idea is to have something like this:
01-0414 / 02-0414 /03-0414 / 04-0414
where the first two digits should be the consecutive number, and the last four digits are the month and year.
I'm using spring 3.2.2 and hibernate 4.2.6. I really appreciate any help about this.
thanks
Well, your question is not clear. But as far as I understand you need help to get the date. You can use Calendar() or Date(), use something like this Calendar.get(Calendar.MONTH)to get the month and year (or simply parse to string and substring where you want).
Regarding the number at the beginning, I will assume (again, since you are not clear) that it is passed as an input. So basically you concatenate that with the "-" and the output of the previous step; the date thingy.
I hope I helped!
If you want to encode your web app string using a sequence number that gets reset to 1 at the beginning of each month, you could use a singleton class instance to hold the month and sequence number state. The code string generator method checks whether the month has changed, and if so, it resets the internal current month to the new month, and resets the effective internal sequence number to 1.
Here is the generator class (see below for an example of how to use it):
public class MySequenceCodeStringGenerator {
private static final int generatorMonth;
private static final int generatorSequenceNumber;
// Create a singleton instance to hold month and sequence number state.
private static final MySequenceCodeStringGenerator INSTANCE = new MySequenceCodeStringGenerator();
private MySequenceCodeStringGenerator() {
generatorMonth = getCurrentMonth();
generatorSequenceNumber = 0;
}
/////////////////////////
// PUBLIC functions:
/////////////////////////
// Get the singleton instance:
public static MySequenceCodeStringGenerator getInstance() {
return INSTANCE;
}
// Get the formatted sequence code string:
public static int getSequenceCodeString {
int sequenceNumber = getSequenceNumber();
Calendar now = Calendar.getInstance();
int year = now.get(Calendar.YEAR);
int month = now.get(Calendar.MONTH);
String yearString = String.valueOf(year);
return String.format( "%02d-%02d%s", sequenceNumber, month+1, yearString.substring(2) );
}
// Get the current month:
private int getCurrentMonth() {
Calendar now = Calendar.getInstance();
return now.get(Calendar.MONTH);
}
// Get the singleton sequence number. Update if this is a new month.
private int getSequenceNumber() {
currentMonth = getCurrentMonth();
if ( currentMonth != generatorMonth ) {
generatorMonth = currentMonth;
generatorSequenceNumber = 0;
}
return ++generatorSequenceNumber;
}
}
Here's an example of how you use the generator class:
String myWebAppString = MySequenceCodeStringGenerator.getInstance().getSequenceCodeString();
Related
I have a String date format (e.g. dd/MM/yyyy) and want to convert it to a US-style with the month first (e.g. MM/dd/yyyy), programatically.
The use-case of this is to read some data and determine which format fits best.
This sounds trivially easy, but having actually tried implementing it, my solution seems sub-optimal.
Below is my attempt, including a test.
public class DateSwapperExample
{
private static final char dateFormatDayLetter = 'd', dateFormatMonthLetter = 'M';
/**
* Swaps the Day & Month component in a Date Format, if both are present <br>
* When swapping, ensures the frequency is retained - e.g. dd/MMM -> MMM/dd <br>
* TODO Only handles one instance of each tag <br>
* TODO This doesn't handle quoted elements in the Date Format (e.g. "dd/mm 'since dave made the best cakes' yyyy")
*/
private static String swapDayAndMonthInDateFormat(final String dateFormat)
{
// Get the position of the groups
final int[] dayIndex = new int[] {dateFormat.indexOf(dateFormatDayLetter), dateFormat.lastIndexOf(dateFormatDayLetter)};
final int[] monthIndex = new int[] {dateFormat.indexOf(dateFormatMonthLetter), dateFormat.lastIndexOf(dateFormatMonthLetter)};
if ((dayIndex[0] == -1) || (monthIndex[0] == -1))
{
// Cannot swap as dateFormat does not contain both dateFormatDayLetter & dateFormatMonthLetter
return dateFormat;
}
else
{
final int[] firstGroup, secondGroup;
// Work out which group comes first
if (dayIndex[0] < monthIndex[0])
{
firstGroup = dayIndex;
secondGroup = monthIndex;
}
else
{
firstGroup = monthIndex;
secondGroup = dayIndex;
}
// Split the string up into segments, re-organise and combine
// The other parts of the format at the start
return substringConstrained(dateFormat, 0, firstGroup[0])
// The second group
+ substringConstrained(dateFormat, secondGroup[0], secondGroup[1] + 1)
// The other parts of the format in the middle
+ substringConstrained(dateFormat, firstGroup[1] + 1, secondGroup[0])
// The first group
+ substringConstrained(dateFormat, firstGroup[0], firstGroup[1] + 1)
// The other parts of the format at the end
+ substringConstrained(dateFormat, secondGroup[1] + 1, dateFormat.length());
}
}
/** Extension of {#link String#substring(int, int)} that constrains the index parameters to be within the allowed range */
private static String substringConstrained(final String str, final int beginIndex, final int endIndex)
{
return str.substring(constrainToRange(beginIndex, 0, str.length()), constrainToRange(endIndex, 0, str.length()));
}
/** Copy of {#link com.google.common.primitives.Ints#constrainToRange(int, int, int)} to avoid the need of Guava in this example */
private static int constrainToRange(int value, int min, int max)
{
return Math.min(Math.max(value, min), max);
}
#org.junit.Test
public void testSwapDayAndMonthInDateFormat()
{
org.junit.Assert.assertEquals("Md", swapDayAndMonthInDateFormat("dM"));
org.junit.Assert.assertEquals("MMd", swapDayAndMonthInDateFormat("dMM"));
org.junit.Assert.assertEquals("Mdy", swapDayAndMonthInDateFormat("dMy"));
org.junit.Assert.assertEquals("Myd", swapDayAndMonthInDateFormat("dyM"));
org.junit.Assert.assertEquals("yMd", swapDayAndMonthInDateFormat("ydM"));
org.junit.Assert.assertEquals("aMbdc", swapDayAndMonthInDateFormat("adbMc"));
org.junit.Assert.assertEquals("MM/dd/yyyy", swapDayAndMonthInDateFormat("dd/MM/yyyy"));
org.junit.Assert.assertEquals("MMM/dd/yyyy", swapDayAndMonthInDateFormat("dd/MMM/yyyy"));
for (final String str : new String[] {"ydy", "yMy", "yDy", "ymy", "Dm", "Dmm", "DD/mm/yyyy", "DD/mmm/yyyy"})
{
org.junit.Assert.assertEquals(str, swapDayAndMonthInDateFormat(str));
}
}
}
private static String swapDayAndMonthInDateFormat(final String dateFormat)
{
return dateFormat.replaceFirst("(d+)(.*?)(M+)", "$3$2$1");
}
I am far from convinced that this is the good solution to your real problem. But it makes you test pass.
Also you should not want to use SimpleDateFormat. That class is notoriously troublesome and along with Date and friends long outdated. Instead use DateTimeFormatter and other classes from java.time, the modern Java date and time API. Format pattern strings still look similar, though, so it could be that this answer is still relevant.
If I use:
GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance();
boolean yearIsLeapYear = cal.isLeapYear(2016);
Then my varialbe yearIsLeapYear is correctly set to true. However, if I use a variable in place of 2016 it doesn't not work.
int year = 2016;
GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance();
boolean yearIsLeapYear = cal.isLeapYear(year);
Am I missing something or is it not possible to pass a variable into the isLeapyYear() method? In the program I'm writing the value in the year field can change depending on user input and the final algorithm I'm implementing needs to behave differently when the current year is a leap year or the next year is a leap year. I thought this would be simple way to perform the check.
Edit showing full code
Fields are:
private int year;
private boolean yearIsLeapYear , nextYearIsLeapYear, previousYearIsLeapYear;
I have a constructor as follows:
public FirstDayOfSummer(int currentYear) {
year = currentYear;
checkForLeapYears();
}
And the following method which I am calling in the constructor:
private void checkForLeapYears(){
GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance();
//checking for a leap year using the current value of "year"
if(cal.isLeapYear(year)){
yearIsLeapYear = true;
}
else{
yearIsLeapYear = false;
}
//checking for a leap year using the value of "year" + 1
if(cal.isLeapYear(year + 1){
nextYearIsLeapYear = true;
}
else{
nextYearIsLeapYear = false;
}
//checking for a leap year using the value of "year" - 1
if(cal.isLeapYear(year - 1){
previousYearIsLeapYear = true;
}
else{
previousYearIsLeapYear = false;
}
}
The error was in calling my constructor.
FirstDayOfSummer currentYearFirstDayOfSummer = new FirstDayOfSummer(Calendar.getInstance().get(Calendar.YEAR));
currentYearFirstDayOfSummer.setYear(2015);
I was accidently using the current year in the constructor and then trying to use a mutator method to change it to something else. Because my method to check for a leap year was only being called in the constructor and not also in the mutator it was never updating my booleans!
Thanks for asking good questions!
I have homework where I have to write a small program that asks for a number and returns the month assigned to that number.
So far I have written two different classes, one to prompt the user for int, and the other with the arrays of month. Now my problem is to pass over the months to the main class when the user enters a number.
So far for the main class I have this and I have no idea on how to proceed...
I get:
java:17: error: array required, but Date found System.out.println(monthName[index]);
I tried to be as detailed as possible.
import java.util.Scanner;
public class Driver {
public static void main(String[] args)
{
Utility input = new Utility();
final int MONTH_NAMES = 12;
int[] month = new int[MONTH_NAMES];
Date monthName = new Date();
{
System.out.println(input.queryForInt("Enter the number for a month ")) ;
}
for (int index = 0; index < 12; index++)
System.out.println(monthName[index]);
}
}
Your System.out line is not referencing the array you named month.
I don't think you intended to use Date monthName here
System.out.println(monthName[index]);
Judging by the number of indexes your for loop is counting, it looks like you wanted to use int[] month.
System.out.println(month[index]);
mouthName is a Date object, not an array. Also, why use a for loop to print out a whole year's mouth?
I think it can change the last for loop to System.out.printLn(mouthName.getMouth()) if the input.queryForIntmethod can successfully pass the int mouth to the mouthName object.
For example, I have input parameter this format: "04:00-06:00" or "23:00-24:00". Type of parameter - String.
And in my method I must check, that time range in input parameter NOT before current time. How I can do it?
More details:
input time range: "12:00-15:00"
current time: 16:00.
In this case, method must return false.
Another example:
input time range: "10:30-12:10"
current time: 09:51.
method must return true.
Can you please give me some idea or algorithm? How I can implement this method?
First off, you should probably just learn to use Joda time.
That said, since the times are all zero padded, you can just compare strings lexically.
public static boolean inRange(String time, String range) {
return time.compareTo(range.substring(0, 5)) >= 0
&& time.compareTo(range.substring(6)) <= 0;
}
It's good practice to fail fast on malformed inputs.
private static final Pattern VALID_TIME = Pattern.compile("[012][0-9]:[0-5][0-9]");
private static final Pattern VALID_RANGE = Pattern.compile("[012][0-9]:[0-5][0-9]-[012][0-9]:[0-5][0-9]");
and then put an assert at the top of inRange:
assert VALID_TIME.matcher(time).matches() : time
assert VALID_RANGE.matcher(range).matches() : range
EDIT:
If you really need to represent the current time as a Date, then you should compare it this way:
public final class Range {
/** Inclusive as minutes since midnight */
public final int start, end;
public Range(int start, int end) {
assert end >= start;
}
/** #param time in minutes since midnight */
public boolean contains(int time) {
return start <= time && time <= end;
}
public static Range valueOf(String s) {
assert VALID_RANGE.matcher(s).matches() : s;
return new Range(minutesInDay(s.substring(0, 5)),
minutesInDay(s.substring(6));
}
private static int minutesInDay(String time) {
return Integer.valueOf(time.substring(0, 2)) * 60
+ Integer.valueOf(time.substring(3));
}
}
Use Range.valueOf to convert from a String, convert your Date to a number of minutes since midnight in whatever timezone you like using whatever calendar implementation you like, and then use Range.contains.
Date currentDate = new Date();
Date maxDate;
Date minDate;
//Parse range to two substrings
//parse two substrings to [HH, MM]
//for HH && MM parseInt()
//
minDate= new Date.SetHour(HH); minDate.SetMinute(MM);
//repeat for max date
if(currentDate.Before(maxDate) && currentDate.After(minDate))
{
return true;
}
else
return false;
I've a code to get year, month and day for one of my application.
package com.cera.hyperionUtils;
import java.util.*;
public class HypDate {
public static int curdate(int field)
{
//1. Specify integer 1 for YEAR, 2 for MONTH, 5 DAY_OF_MONTH
Calendar c = new GregorianCalendar();
c.setLenient(true); //Allow overflow
//2. Extract and Return result
if (field == 2) {
field = c.get(Calendar.MONTH) + 1;
}
return c.get(field);
}
public static void main(String[] args)
{
System.out.println(HypDate.curdate(2));
}
}
But when i pass 2 it is giving 0 year and day prints correctly.....Also i was trying to make month as double digit. (like 01 for 1)
Can someone please help me....? (I''m very new to java coding)
Rather than returning these one by one, you may just want to use a SimpleDateFormat to format it.
Say I want a date as year-month-day:
// Necessary imports
import java.text.DateFormat;
import java.text.SimpleDateFormat;
// Declare class and stuff before this
public static String getFormattedDate() {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
return df.format(new Date());
}
public static void main(String[] args) {
System.out.println(getFormattedDate());
}
Outputs 2010-10-29
Edit:
Since you just want the month, you can do this:
public static String getFormattedMonth() {
DateFormat df = new SimpleDateFormat("MM");
return df.format(new Date());
}
if (field == 2) {
field = c.get(Calendar.MONTH) + 1;
}
return c.get(field);
You retrieve the correct month as an index and then use that index to retrieve another field that will be unknown and related in how the constants are saved. Just return the value before, without using a second get.
Maybe you meant
if (field == 2) {
field = Calendar.MONTH;
}
return c.get(field) + 1;
but I don't get why you are redefining that constants instead that use the one already provided..
The problem comes from the fact that when you are getting the month information, you call c.get() twice, which you don't want to do. Instead, you should directly return after you get the first value
//1. Specify integer 1 for YEAR, 2 for MONTH, 5 DAY_OF_MONTH
Calendar c = new GregorianCalendar();
c.setLenient(true); //Allow overflow
//2. Extract and Return result
if (field == Calendar.MONTH) {
return c.get(field) + 1; //because Java months are 0-based
} else {
return c.get(field);
}