XMLGregorianCalendar format date in ZonedDateTime - datetime

I have a function which takes Date and gives XMLGregorianCalendar formatted date as below which returns date as 2017-11-30T00:00:00.000-08:00 when date provided as 2017-11-30
public static String xmlDate(Date date) {
XMLGregorianCalendar xmlDate = null;
if (date != null) {
GregorianCalendar gc = new GregorianCalendar();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
gc.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
gc.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
gc.set(Calendar.MILLISECOND, 0);
try {
xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
} catch (DatatypeConfigurationException e) {
//exception
}
}
return xmlDate.toString();
}
I'm trying to rewrite above function with Java 8 ZonedDateTime but getting date as 2017-11-29T00:00:00-08:00 .How can I get the exact output same as the above function? Also I dont understand why the date is 29 instead of 30.
public static String zonedDatetime(Date date) {
return ZonedDateTime.ofInstant(date.toInstant(), ZoneId.of("America/Los_Angeles"))
.truncatedTo(ChronoUnit.DAYS)
.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
}

Assuming that date is this instant, then the reason you are getting the 29th is because that is the date in Los Angeles at this moment (22:53 PST).
If you want to match the local date, then you're probably after something like this:
return ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault())
.withZoneSameLocal(ZoneId.of("America/Los_Angeles"))
.truncatedTo(ChronoUnit.DAYS)
.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)

Related

How to set datetime through Groovy setter

i have a long value then i convert the Longvalue in datetime format. I am not sure if the conversion is in the right way, but i am able to get in the right format. Now i am struggling to set the converterted datetime in groovy using setter. #formattedDate can be in date format, i do not know how to save in datetime. I get the error conversion String datetime. Please help.
def time= 1550670822 / 1000;
LocalDateTime dateTime = LocalDateTime.ofEpochSecond(time, 0, ZoneOffset.UTC);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss", Locale.ENGLISH);
String formattedDate = dateTime.format(formatter);
trial.setFinishingTime(formattedDate);
In my class i have for setFinishingTime.
public String getFinishingTime()
{
return getPropertyContainer().getString(FINISHING_TIME, "")
}
public void setFinishingTime(String finishingTime)
{
getPropertyContainer().setString(FINISHING_TIME, finishingTime)
}
This part i am not sure, should it be like this in DateTime format:
public DateTime getFinishingTime()
{
return getPropertyContainer().getDate(FINISHING_TIME, "")
}
public void setFinishingTime(DateTime finishingTime)
{
getPropertyContainer().setDate(FINISHING_TIME, finishingTime)
}
If i change this to DateTime how can i store a DateTime of dd:mm:yyyy pattern which i get from the above code. Please help

Formatting Joda time with Ethiopic Chronology not displaying the name of the month

I'm using Joda time to convert gregorian date and time to Ethiopic chronology and I'm trying to format it with "MMMM dd, yyyy" format. I expect the Date to be displayed as "Meskerem 01, 2007" instead I get "1 01, 2007". Is this a bug in Joda time or am I doing something wrong?
DateTimeFormatter dtf = DateTimeFormat.forPattern("MMMM dd, yyyy")
Date time myDate = new DateTime(2014,9,11,0,0,0,0).withChronology(EthiopicChronology.getInstance()).toString(dtf)
Well, JodaTime has never been good in internationalization, sorry. But I will present a workaround.
DateTimePrinter printer =
new DateTimePrinter() {
#Override
public int estimatePrintedLength() {
return 8; // type the maximum chars you need for printing ethiopic months
}
#Override
public void printTo(StringBuffer buf, ReadablePartial partial, Locale locale) {
int index = LocalDate.now().indexOf(DateTimeFieldType.monthOfYear());
int month = partial.getValue(index);
print(buf, month);
}
#Override
public void printTo(Writer out, ReadablePartial partial, Locale locale)
throws IOException
{
StringBuffer sb = new StringBuffer();
printTo(sb, partial, locale);
out.write(sb.toString());
}
#Override
public void printTo(
StringBuffer buf,
long instant,
Chronology chrono,
int displayOffset,
DateTimeZone displayZone,
Locale locale
) {
LocalDate date = new LocalDate(instant, EthiopicChronology.getInstance());
print(buf, date.getMonthOfYear());
}
#Override
public void printTo(
Writer out,
long instant,
Chronology chrono,
int displayOffset,
DateTimeZone displayZone,
Locale locale
) throws IOException
{
StringBuffer sb = new StringBuffer();
printTo(sb, instant, chrono, displayOffset, displayZone, locale);
out.write(sb.toString());
}
private void print(StringBuffer buf, int month) {
switch (month) {
case 1 : // attention: ethiopic month index
buf.append("Meskerem");
break;
// case 2: etc.
default :
buf.append(month);
}
}
};
DateTimeFormatter dtf =
new DateTimeFormatterBuilder().append(printer).appendPattern(" dd, yyyy").toFormatter();
Chronology chronology = EthiopicChronology.getInstance();
DateTime ethiopic = new DateTime(2014, 9, 11, 0, 0, 0).withChronology(chronology);
String myDate = ethiopic.toString(dtf);
System.out.println(ethiopic); // 2007-01-01T00:00:00.000+02:00 (ethiopic month number and year and day-of-month!!!)
System.out.println(myDate); // Meskerem 01, 2007
Just to note: This code (as suggested by #Opal?) does not work for me:
Chronology chronology = EthiopicChronology.getInstance();
DateTimeFormatter dtf =
DateTimeFormat.forPattern("MMMM dd, yyyy").withChronology(chronology);
String myDate = new DateTime(2014, 9, 11, 0, 0, 0).toString(dtf2);
System.out.println(myDate); // 1 01, 2007
The reason is the sad fact that Joda-Time does not manage its own text resources for non-gregorian chronologies, compare also this SO-post. You can also use a specialized field implementation as suggested in that post. Here I have presented a solution using DateTimePrinter on which you have to add the missing month names you need.
Have a look at the example below:
#Grab(group='joda-time', module='joda-time', version='2.7')
import org.joda.time.format.DateTimeFormat
import org.joda.time.format.DateTimeFormatter
import org.joda.time.DateTime
import org.joda.time.chrono.EthiopicChronology
DateTimeFormatter dtf = DateTimeFormat.forPattern("MMMM dd, yyyy")
println new DateTime(2014,9,11,0,0,0,0).toString(dtf)
It prints the date correctly - full month name. Now have a look at the docs. It states that Chronology object returns a new formatter. Probably this is not a bug but the just returned formatter is used instead of the one defined.
UPDATE
It might be a bug, it doesn't work with BuddhistChronology as well:
#Grab(group='joda-time', module='joda-time', version='2.7')
import org.joda.time.format.DateTimeFormat
import org.joda.time.format.DateTimeFormatter
import org.joda.time.DateTime
import org.joda.time.chrono.*
DateTimeFormatter dtf = DateTimeFormat.forPattern("MMMM dd, yyyy")
println new DateTime(2014,9,11,0,0,0,0).withChronology(BuddhistChronology.getInstance()).toString(dtf)

Correctly convert DateTime property with Dapper on SQLite

I'm using Dapper to insert and get objects to/from SQLite: one object have a property of type DateTime (and DateTimeOffset) that I have to persist and retrieve with milliseconds precision. I can't find a way to correctly retrieve the value because Dapper fail with:
System.FormatException : String was not recognized as a valid DateTime.
in System.DateTimeParse.ParseExactMultiple(String s, String[] formats, DateTimeFormatInfo dtfi, DateTimeStyles style)
in System.DateTime.ParseExact(String s, String[] formats, IFormatProvider provider, DateTimeStyles style)
in System.Data.SQLite.SQLiteConvert.ToDateTime(String dateText, SQLiteDateFormats format, DateTimeKind kind, String formatString)
in System.Data.SQLite.SQLite3.GetDateTime(SQLiteStatement stmt, Int32 index)
in System.Data.SQLite.SQLite3.GetValue(SQLiteStatement stmt, SQLiteConnectionFlags flags, Int32 index, SQLiteType typ)
in System.Data.SQLite.SQLiteDataReader.GetValue(Int32 i)
in System.Data.SQLite.SQLiteDataReader.GetValues(Object[] values)
in Dapper.SqlMapper.<>c__DisplayClass5d.<GetDapperRowDeserializer>b__5c(IDataReader r) in SqlMapper.cs: line 2587
in Dapper.SqlMapper.<QueryImpl>d__11`1.MoveNext() in SqlMapper.cs: line 1572
in System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
in System.Linq.Enumerable.ToList(IEnumerable`1 source)
in Dapper.SqlMapper.Query(IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) in SqlMapper.cs: line 1443
in Dapper.SqlMapper.Query(IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) in SqlMapper.cs: line 1382
What do I have to try? Column is of type DATETIME.
Do I have to create a custom TypeHandler and convert DateTime to and from a SQLite string in format "o"?
Dapper version 1.38
I know it's old, but I have found the solution.
After a lot of digging and analyzing Dapper code I came up with this (notice that this is 2019 year):
First you will have to create date time handler:
public class DateTimeHandler : SqlMapper.TypeHandler<DateTimeOffset>
{
private readonly TimeZoneInfo databaseTimeZone = TimeZoneInfo.Local;
public static readonly DateTimeHandler Default = new DateTimeHandler();
public DateTimeHandler()
{
}
public override DateTimeOffset Parse(object value)
{
DateTime storedDateTime;
if (value == null)
storedDateTime = DateTime.MinValue;
else
storedDateTime = (DateTime)value;
if (storedDateTime.ToUniversalTime() <= DateTimeOffset.MinValue.UtcDateTime)
return DateTimeOffset.MinValue;
else
return new DateTimeOffset(storedDateTime, databaseTimeZone.BaseUtcOffset);
}
public override void SetValue(IDbDataParameter parameter, DateTimeOffset value)
{
DateTime paramVal = value.ToOffset(this.databaseTimeZone.BaseUtcOffset).DateTime;
parameter.Value = paramVal;
}
}
Now, notice that Dapper translates .Net's type DateTimeOffset to dbType - DateTimeOffset. You need to remove this mapping and add your own like this:
SqlMapper.RemoveTypeMap(typeof(DateTimeOffset));
SqlMapper.AddTypeHandler(DateTimeHandler.Default);
That's all. Now everytime Dapper will see DateTimeOffset property in your model, it will run your DateTimeHandler to manage this.
I have found that custom TypeHandler for base types can't be used because of default typeMap that is choosen before looking for TypeHandler.
I have opened an issue dapper-dot-net but in the mean time I have solved replacing via reflection the default typeMap with a new one like the previous minus the four key DateTime, DateTime?, DateTimeOffset, DateTimeOffset?
I've made a slight modification to Adam Jachocki's solution as it didn't work for me. I am storing a date as TEXT in Sqlite and Dapper was giving me a string instead of a DateTime as the object value to parse. Apparently, Sqlite stores datetime values using three different data types: INTEGER (unix epoch), TEXT (ISO 8601 YYYY-MM-DD HH:MM:SS.SSS), and REAL ("number of days since noon in Greenwich on November 24, 4741 B.C."). That last one is really out there, so it isn't supported in the code below.
See the sqlite docs and this page for more info.
Below is my implementation of the DateTimeOffset TypeHandler. The rest of Adam's solution remains the same.
internal class DateTimeOffsetHandler : SqlMapper.TypeHandler<DateTimeOffset>
{
private static readonly TimeZoneInfo databaseTimeZone = TimeZoneInfo.Local;
private static readonly DateTime unixOrigin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
public static DateTimeOffsetHandler Default { get; } = new DateTimeOffsetHandler();
public DateTimeOffsetHandler() {}
public override DateTimeOffset Parse(object value)
{
if (!TryGetDateTime(value, out DateTime storedDateValue))
{
throw new InvalidOperationException($"Unable to parse value {value} as DateTimeOffset");
}
if (storedDateValue.ToUniversalTime() <= DateTimeOffset.MinValue.UtcDateTime)
{
return DateTimeOffset.MinValue;
}
else
{
return new DateTimeOffset(storedDateValue, databaseTimeZone.BaseUtcOffset);
}
}
public override void SetValue(IDbDataParameter parameter, DateTimeOffset value)
{
DateTime paramVal = value.ToOffset(databaseTimeZone.BaseUtcOffset).DateTime;
parameter.Value = paramVal;
}
private bool TryGetDateTime(object value, out DateTime dateTimeValue)
{
dateTimeValue = default;
if (value is DateTime d)
{
dateTimeValue = d;
return true;
}
if (value is string v)
{
dateTimeValue = DateTime.Parse(v);
return true;
}
if (long.TryParse(value?.ToString() ?? string.Empty, out long l))
{
dateTimeValue = unixOrigin.AddSeconds(l);
return true;
}
if (float.TryParse(value?.ToString() ?? string.Empty, out float f))
{
throw new InvalidOperationException("Unsupported Sqlite datetime type, REAL.");
}
return false;
}
}

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;
}

Date giving exception in US server

I am getting a date string from the javascript and converting that to Datetime and save that to the database.
But in the Indian server my code working fine. But when I upload my code to US based server it's giving exception. Is there any common way to make my code runnable to all the server.
My code is like below
[WebMethod(EnableSession = true)]
public static bool submitDate( string date ) // format is dd-mm-yyyy 20-01-2011
{
DateTime DOBdate = DateTime.Now;
double age = 0.0;
if (DateTime.TryParse(date , out DOBdate))
{
age = (DateTime.Now - DOBdate).Days / 365;
}
dbcmd.Parameters.Add("#DateOfBirth", SqlDbType.DateTime).Value = Convert.ToDateTime(DOBdate);
}
Please help me.
the exception which is showing is
SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
You should use TryParseExact, I guess the default datetime format of the server is not dd-mm-yyyy. And you should handle the if of the parse function:
public static bool submitDate( string date ) // format is dd-mm-yyyy 20-01-2011
{
DateTime DOBdate = DateTime.Now;
double age = 0.0;
if (DateTime.TryParseExact(date , {"dd-MM-yyyy"},
null,
DateTimeStyles.None,
out DOBdate))
{
age = (DateTime.Now - DOBdate).Days / 365;
}
else
{
// Handle this case!
}
dbcmd.Parameters.Add("#DateOfBirth", SqlDbType.DateTime).Value = Convert.ToDateTime(DOBdate);
}
BTW your age function is not a realy good indication of the age. The older your person, the more faulty it gets.

Resources