This question already has answers here:
How to convert a String of format yyyymmdd to LocalDate in JodaTime [duplicate]
(1 answer)
Change date format in a Java string
(22 answers)
Good way to convert integer YYYYMMDD into java.util.Date with local time zone
(4 answers)
Closed 3 years ago.
I am trying to process the data from a weather station. I simply want to process and print (for now) the minimum and maximum temperatures each day starting from 2000/01/01 until today 2019/12/12. The weather station gives me the date in an integer yyyymmdd like 20191212 or 20030317. I store this, alongside the minimum and maximum temperatures in an integer array, of about 21000 rows long... I want the date to be displayed in yyyy/mm/dd, like 2019/12/12 or 2003/03/17. How exactly do I go about doing this?
This is my code
import java.io.*;
public class Main {
public static void main(String args[]) {
int rowAmount = 7152; //the amount of rows in the document
int[] temperatures = new int[rowAmount*3]; //makes an array 3 times the size of rowAmount, to fit date, min temp and max temp.
try {
BufferedReader br = new BufferedReader(new FileReader("D:\\20002019minmaxtempbilt.txt")); // Makes the filereader
String fileRead = br.readLine(); // reads first like
int counter = 0; //sets a counter
while (fileRead != null) { // loops until the file ends.
String[] tokenize = fileRead.split(","); //splits the line in 3 segements, date, min temp and max temp. And stores them in following variables
int tempDate = Integer.parseInt(tokenize[0]);
int tempMin = Integer.parseInt(tokenize[1]);
int tempMax = Integer.parseInt(tokenize[2]);
//adds the values to the array
temperatures[counter] = tempDate;
counter++;
temperatures[counter] = tempMin;
counter++;
temperatures[counter] = tempMax;
}
// close file stream
br.close();
}
catch (FileNotFoundException fnfe)
{
System.out.println("file not found");
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
// Displays the entire array, formatted by date neatly, hopefully.
for(int i = 0; i<rowAmount; i =+ 3) {
int tempDate = temperatures[i];
int tempMin = temperatures[i+1];
int tempMax = temperatures[i+2];
drawLine(tempDate, tempMin, tempMax);
}
}
public static void drawLine(int tempDate, int tempMin, int tempMax) {
/*This is where I get stuck. I need to convert tempDate from an int yyyymmdd to either
3 separate integers representing year, month and day; or I need to convert it to a
string that can be printed out yyyy/mm/dd.*/
System.out.printf("");
}
}
Since your date is a String to start with I see no reason to convert it to an Integer first. Using the more current java.time package you can use one formatter to convert from a String to LocalDate and then another to convert back to a String with the right format,
DateTimeFormatter inFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate date = LocalDate.parse(tokenize[0], inFormatter);
DateTimeFormatter outFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
String outStr = outFormatter.format(date);
Since DateTimeFormatter is costly to initialise I would recommend you create both of them before the loop you have for reading the file.
Another way: if the integer value representing the date is stored in an int called date (example value: 20191212), then
int day = date % 100;
int month = (date/ 100) % 100;
int year = date / 10000;
then you can use a Formatter to format the string output that you want.
A problem is that an integer of 20191212 really doesn't represent a date.
I would recommend NOT transforming tempDate into an integer and leaving it as a string.
Edit
Here is an example that uses the Java 8 time package classes: LocalDate, DateTimeFormatter, and DateTimeFormatterBuilder:
package stackoverflow;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
public class ParseStringDate {
public static void main(String... args) {
String dateString = "20191231";
DateTimeFormatter dateTimeFormatterParser = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate localDate = LocalDate.parse(dateString, dateTimeFormatterParser);
System.out.println(localDate);
DateTimeFormatter dateTimeFormatterPrinter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
System.out.println(localDate.format(dateTimeFormatterPrinter));
dateTimeFormatterPrinter = new DateTimeFormatterBuilder()
.appendPattern("yyyy")
.appendLiteral("/")
.appendPattern("MM")
.appendLiteral("/")
.appendPattern("dd").toFormatter();
System.out.println(localDate.format(dateTimeFormatterPrinter));
}
}
Here is an example that uses SimpleDateFormat:
package stackoverflow;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateFormattingFromString {
public static void main(String... args) throws Exception {
String tempDate = "20191212";
SimpleDateFormat sdf1 = new SimpleDateFormat("YYYYmmdd");
Date date = sdf1.parse(tempDate);
// Now format the above date as needed...
SimpleDateFormat sdf2 = new SimpleDateFormat("YYYY/mm/dd");
System.out.println(sdf2.format(date));
}
}
As pointed out in the comments, SimpleDateFormat and the Date classes are not super great to work with. They are mutable and therefore not thread safe. The new java.time package classes are immutable and therefore thread safe. The new classes are also easier to do date math with and comparisons.
I'd recommend using a DateFormat object, taking advantage of the parse(String) and format(Date) methods.
Related
So in a Java project I'm working on we are required to use only Date and Calendar objects to represent dates. A method I'm writing requires that a date be at least certain number of years in the past, so I need to be able to accurately calculate the number of years between the present and the given Date or Calendar. I have managed to accurately calculate the number of days between using this implementation:
public static long daysSince(Date pastDate) {
long millisecondsSince = new Date().getTime() - pastDate.getTime();
return TimeUnit.DAYS.convert(millisecondsSince, TimeUnit.MILLISECONDS);
}
However I am now struggling to find a way to accurately calculate the number of years between these dates whilst taking into consideration leap years etc. Obviously dividing the result of the above method by 365 or 365.25 does not quite work. I am aware of the joda time package and java.time however we explicitly need to work with Date and Calendar objects. Anyone got any idea how this can be done, preferably as quickly and elegantly as possible? Thank you
EDIT: Seemed to find functioning solution, see below
I was finally able to implement the desired functionality using the following code (using some ideas from Haseeb Anser's link):
public static int yearsSince(Date pastDate) {
Calendar present = Calendar.getInstance();
Calendar past = Calendar.getInstance();
past.setTime(pastDate);
int years = 0;
while (past.before(present)) {
past.add(Calendar.YEAR, 1);
if (past.before(present)) {
years++;
}
} return years;
}
Preliminary tests seem to be getting correct output from this, but I've yet to test more extensively.
Check this simple example it might help you:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class GetNumberOfYearsBetweenTwoDate {
public int getNumberOfYearsBetweenTwoDate(String strDate1, String dateFormat1,
String strDate2, String dateFormat2) {
int years = 0;
Date date1, date2 = null;
SimpleDateFormat sdf1 = new SimpleDateFormat(dateFormat1);
SimpleDateFormat sdf2 = new SimpleDateFormat(dateFormat2);
SimpleDateFormat sdfYear = new SimpleDateFormat("yyyy");
try {
date1 = (Date)sdf1.parse(strDate1);
date2 = (Date)sdf2.parse(strDate2);
int year1 = Integer.parseInt(sdfYear.format(date1));
int year2 = Integer.parseInt(sdfYear.format(date2));
years = year2 - year1;
} catch (ParseException ex) {
System.err.println(ex.getMessage());
}
return years;
}
public static void main(String[] args) {
String strDate1 = "13-10-1988";
String dateFormat1 = "dd-MM-yyyy";
String strDate2 = "2011-10-13";
String dateFormat2= "yyyy-MM-dd";
GetNumberOfYearsBetweenTwoDate gnoybtd = new
GetNumberOfYearsBetweenTwoDate();
int years = gnoybtd.getNumberOfYearsBetweenTwoDate(strDate1, dateFormat1,
strDate2, dateFormat2);
System.out.println("Number of Years: "+years+" Years");
}
}
I want to display the arraylist like this:
[2013-11-01,2013-11-8,2013-11-15,2013-11-22,2013-11-29]
I am written the below code and i am passing the static values to that method:
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
public class DateExample {
Calendar cal = Calendar.getInstance();
public static void main(String[] args) {
DateExample date=new DateExample();
date.getAllDaysInaMonth("2013",11,1);
}
public List<java.sql.Date> getAllDaysInaMonth(String year,int month,int day){
System.out.println(year+""+month+""+day);
cal.set(Calendar.DAY_OF_MONTH, 1);
int utilyear=cal.get(cal.YEAR);
String syear= Integer.toString(utilyear);
int utilmonth=cal.get(cal.MONTH);
int utilday=cal.get(cal.DAY_OF_MONTH);
List<java.sql.Date> arraylist=new ArrayList<java.sql.Date>();
while (month==cal.get(Calendar.MONTH)) {
System.out.println("while"+cal.getTime());
SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd");
String dateofutil=format.format(cal.getTime());
System.out.println("dateofutil"+dateofutil);
try {
java.sql.Date sqldate=new java.sql.Date(format.parse(dateofutil).getTime());
arraylist.add(sqldate);
} catch (ParseException e) {
e.printStackTrace();
}
cal.add(Calendar.DAY_OF_MONTH,1);
}
System.out.println("arraylist values"+arraylist);
return arraylist;
}
}
Here am passing static year,month,date to method as a parameters through that values am printing the dates like yyyy-MM-dd format when am passing 1 day then after 7 days date is printed
But the above code is not working properly give me correct code
There are two things to be changed here.
First,
while (month==cal.get(Calendar.MONTH)) {
needs to be changed to
while (month==cal.get(Calendar.MONTH)+1) {
because the according to docs
The first month of the year in the Gregorian and Julian calendars is JANUARY which is 0;
and the second thing is to make your ArrayList of type String and not Date, because Date does not have a format. You can only get a formatted String representation of it.
List<String> arraylist = new ArrayList<String>();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); // This can go out of the `while` loop though.
String dateofutil = format.format(cal.getTime());
arraylist.add(dateofutil);
You need to make the change below:
From
while (month==cal.get(Calendar.MONTH)) {
to
while ((month-1)==cal.get(Calendar.MONTH)) {
See more in Calendar.class ==> NOVEMBER , it is 10 rather 11. That's why previously you did not get the expected result. Change it and go ahead.
public final static int NOVEMBER = 10;
/**
* Value of the {#link #MONTH} field indicating the
* twelfth month of the year.
*/
public final static int DECEMBER = 11;
/**
* Value of the {#link #MONTH} field indicating the
* thirteenth month of the year. Although <code>GregorianCalendar</code>
* does not use this value, lunar calendars do.
*/
public final static int UNDECIMBER = 12;
The answer by R.J and the answer by MouseLearnJava are both correct.
This kind of date-time work is much easier using the Joda-Time library.
For one thing, Joda-Time counts from one unlike the zero-based silliness of java.util.Calendar. So the days of week are 1-7, months of year 1-12.
Here is some example code using Joda-Time 2.3 and Java 7.
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;
// Data passed into method.
int year = 2014;
int month = 2;
int day = 2;
java.util.List<DateTime> dateTimes = new ArrayList<DateTime>();
DateTime start = new DateTime( year, month, day, 0, 0, 0 );
DateTime dateTime = start;
while( dateTime.monthOfYear().equals( start.monthOfYear() ) ) {
dateTimes.add( dateTime ); // Collect each date-time object.
dateTime = dateTime.plusDays( 7 );
}
System.out.println( "The list: " + dateTimes );
for( DateTime item : dateTimes ){
System.out.println( ISODateTimeFormat.date().print( item ) );
}
When run…
The list: [2014-02-02T00:00:00.000-08:00, 2014-02-09T00:00:00.000-08:00, 2014-02-16T00:00:00.000-08:00, 2014-02-23T00:00:00.000-08:00]
2014-02-02
2014-02-09
2014-02-16
2014-02-23
please tell me how to parse this date: "29-July-2012"
I try:
new SimpleDateFormat("dd-MMM-yyyy");
but it doesn't works. I get the following exception:
java.text.ParseException: Unparseable date: "29-July-2012"
You need to mention the Locale as well...
Date date = new SimpleDateFormat("dd-MMMM-yyyy", Locale.ENGLISH).parse(string);
In your String, the full format is used for month, so according to http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html you should be using MMMM as suggested in Baz's comment.
The reason for this can be read from the API docs.
http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html#month states that for month it will be interpreted as text if there are more than 3 characters and
http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html#text states that the full form (in your case 'July' rather than 'Jul') will be used for 4 or more characters.
Try this (Added Locale.ENGLISH parameter and long format for month)
package net.orique.stackoverflow.question11815659;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;
public class Question11815659 {
public static void main(String[] args) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMMM-yyyy",
Locale.ENGLISH);
System.out.println(sdf.parse("29-July-2012"));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Use the split() function with the delimiter "-"
String s = "29-July-2012";
String[] arr = s.split("-");
int day = Integer.parseInt(arr[0]);
String month = arr[1];
int year = Integer.parseInt(arr[2]);
// Now do whatever u want with the day, month an year values....
Create a StringTokenizer. You first need to import the library:
import Java.util.StringTokenizer;
Basically, you need to create a delimeter, which is basically something to seperate the text. In this case, the delimeter is the "-" (the dash/minus).
Note: Since you showed the text with quotations and said parse, i'm assuming its a string.
Example:
//Create string
String input = "29-July-2012";
//Create string tokenizer with specified delimeter
StringTokenizer st = new StringTokenizer(input, "-");
//Pull data in order from string using the tokenizer
String day = st.nextToken();
String month = st.nextToken();
String year = st.nextToken();
//Convert to int
int d = Integer.parseInt(day);
int m = Integer.parseInt(month);
int y = Integer.parseInt(year);
//Continue program execution
I need to validate a date mm/dd from a constructor that receives a string variable. I have tried several ways with no luck. Last I tried was to convert string to ascii and validate that way but is not working either:
public Dated(String dateStr)
{
this.dateStr = dateStr;
for (int i = 0; i < dateStr.length(); i++)
{
char c = dateStr.charAt(i);
asciiValues = (int) c; // change each string character to ASCII value
}
}
public void display()
{
System.out.println(asciiValues);
}
As far I know you are troubling in parsing the string values. Right.
In java we have a verity of tools available to validate the things like these.
I will be using SimpleDateFormat Utility class that can validate the date and also convert the Date to String
public class Dated{
private SimpleDateFormat sdf = new SimpleDateFormat("MM/dd") // M --> Month; d--> Day
public Dated(String dateStr) throws Exception{
try{
Date d = sdf.parse(dateStr);
System.out.println( d );
} catch (ParseException e) {
// you can throw that exception just to
// avoid creating the object of this class
throw e;
}
}
}
But remember that you are not validating the date for Leap Year as mention by #JB Nizet.
You can overcome that by validating the Year as well.
In above code if you pass "02/29" you will get the date 1st March. Which is not correct date as 1970 is not a leap year.
So I would include the Year in my date validation as well.
To add the year you can change the SimpleDateFormat as bellow.
private SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy"); // y --> Year
I have a string holding a start time and an end time in this format 8:30AM - 9:30PM I want to be able to strip out the AM - and the PM and convert all the times to 24 hour format so 9:30PM would really be 21:30 and also have both the times stored in 2 different variables, I know how to strip the string into substrings but Im not sure about the conversion, this is what I have so far. the time variable starts out holding 8:30AM - 9:30PM.
String time = strLine.substring(85, 110).trim();
//time is "8:30AM - 9:30PM"
String startTime;
startTime = time.substring(0, 7).trim();
//startTime is "8:30AM"
String endTime;
endTime = time.substring(9).trim();
//endTime "9:30AM"
Working code (considering that you managed to split the Strings):
public class App {
public static void main(String[] args) {
try {
System.out.println(convertTo24HoursFormat("12:00AM")); // 00:00
System.out.println(convertTo24HoursFormat("12:00PM")); // 12:00
System.out.println(convertTo24HoursFormat("11:59PM")); // 23:59
System.out.println(convertTo24HoursFormat("9:30PM")); // 21:30
} catch (ParseException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
}
// Replace with KK:mma if you want 0-11 interval
private static final DateFormat TWELVE_TF = new SimpleDateFormat("hh:mma");
// Replace with kk:mm if you want 1-24 interval
private static final DateFormat TWENTY_FOUR_TF = new SimpleDateFormat("HH:mm");
public static String convertTo24HoursFormat(String twelveHourTime)
throws ParseException {
return TWENTY_FOUR_TF.format(
TWELVE_TF.parse(twelveHourTime));
}
}
Now that I think about it, SimpleDateFormat, H h K k can be confusing.
Cheers.
You need to use: SimpleDateFormat
And can refer this tutorial: Formatting hour using SimpleDateFormat
Example:
//create Date object
Date date = new Date();
//formatting hour in h (1-12 in AM/PM) format like 1, 2..12.
String strDateFormat = "h";
SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
System.out.println("hour in h format : " + sdf.format(date));
I wouldn't reinvent the wheel (unless you are doing this as a school project or some such).
Just get a date object out of your time stamp and then you can generate whatever format you want with this: SimpleDateFormat
[edited to address your specific request]
if you absolutely need to work from your own unique strings, then you'll do something like this (I don't know exactly what your strings look like... you're using offsets like 85, which means nothing out of context).
I didn't check this for bugs, but this is approximately what you want...
myStr = timestampString.toLowerCase(); //something like 8:30am
boolean add12 = (myStr.indexOf("pm") != -1)?true:false;
//convert hour to int
int hour = Integer.parseInt(myStr.split(":")[0]);
int minutes = Integer.parseInt( myStr.split(":")[1].replaceAll("\\D+","").replaceAll("^0+","") ); //get the letters out of the minute part and get a number out of that, also, strip out leading zeros
int militaryTime = hour + (add12)? 12:0;
if(!add12 && militaryTime == 12)
militaryTime = 0; //account for 12am
//dont' forget to add the leading zeros back in as you assemble your string
With Joda Time, the code looks like:
DateTimeFormatter formatter12 = DateTimeFormat.forPattern("K:mma");
DateTime begin = formatter12.parseDateTime(beginTime);
DateTime end = formatter12.parseDateTime(endTime);
DateTimeFormatter formatter24 = DateTimeFormat.forPattern("k:mma");
String begin24 = formatter24.print(begin);
String end24 = formatter24.print(end);
I should like to contribute the modern answer
DateTimeFormatter twelveHourFormatter = DateTimeFormatter.ofPattern("h:mma", Locale.ENGLISH);
String time = "8:30AM - 9:30PM";
String[] times = time.split(" - ");
LocalTime start = LocalTime.parse(times[0], twelveHourFormatter);
System.out.println(start.toString());
LocalTime end = LocalTime.parse(times[1], twelveHourFormatter);
System.out.println(end.toString());
This prints:
08:30
21:30
I am using java.time, the modern Java date and time API. The SimpleDateFormat class used in many of the other answers is long outdated and was always troublesome. java.time is so much nicer to work with than the date-time classes from the 1990’s. A LocalTime is a time of day without a date (and without time zone), so suits your need much better than an old-fashioned Date.
Link: Oracle tutorial: Date Time explaining how to use java.time.
24 hour time adds 12 to any time greater than 12pm so that 1pm is 13 and so on until 24 or 12am. Here is the sudo code:
if(hour <= 12)
{
hour = hour + 12;
}
All the below lines will works when
String str="07:05:45PM";
and when you call timeConversion(str) and want to convert to 24 hours format..
public class TimeConversion {
private static final DateFormat TWELVE_TF = new SimpleDateFormat("hh:mm:ssa");
private static final DateFormat TWENTY_FOUR_TF = new SimpleDateFormat("HH:mm:ss");
static String timeConversion(String s) {
String str = null;
try {
str= TWENTY_FOUR_TF.format(
TWELVE_TF.parse(s));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return str;
}
public static void main(String[] args) throws ParseException {
String str="07:05:45PM";
System.out.println(timeConversion(str));
}
}