1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package test.sql;
  24 
  25 import java.sql.Date;
  26 import java.sql.Time;
  27 import java.sql.Timestamp;
  28 import java.time.Instant;
  29 import java.time.LocalDateTime;
  30 import java.time.ZoneId;
  31 import java.util.Calendar;
  32 import java.util.TimeZone;
  33 import static org.testng.Assert.*;
  34 import org.testng.annotations.AfterClass;
  35 import org.testng.annotations.BeforeClass;
  36 import org.testng.annotations.DataProvider;
  37 import org.testng.annotations.Test;
  38 import util.BaseTest;
  39 
  40 public class TimestampTests extends BaseTest {
  41 
  42     private static TimeZone defaultTimeZone = null;
  43 
  44     /*
  45      * Need to set and use a custom TimeZone which does not
  46      * observe daylight savings time for this test.
  47      */
  48     @BeforeClass
  49     public static void setUpClass() throws Exception {
  50         defaultTimeZone = TimeZone.getDefault();
  51         TimeZone tzone = TimeZone.getTimeZone("GMT+01");
  52         assertFalse(tzone.observesDaylightTime());
  53         TimeZone.setDefault(tzone);
  54     }
  55 
  56     /*
  57      * Conservatively reset the default time zone after test.
  58      */
  59     @AfterClass
  60     public static void tearDownClass() throws Exception {
  61         TimeZone.setDefault(defaultTimeZone);
  62     }
  63 
  64     /*
  65      * Validate an IllegalArgumentException is thrown for an invalid Timestamp
  66      */
  67     @Test(dataProvider = "invalidTimestampValues",
  68             expectedExceptions = IllegalArgumentException.class)
  69     public void test(String ts) throws Exception {
  70         Timestamp.valueOf(ts);
  71     }
  72 
  73     /*
  74      * Validate that two Timestamp are equal when the leading 0 in seconds is
  75      * omitted
  76      */
  77     @Test
  78     public void test01() throws Exception {
  79         String testTS = "2009-01-01 10:50:00";
  80         String ExpectedTS = "2009-01-01 10:50:0";
  81         Timestamp ts = Timestamp.valueOf(testTS);
  82         Timestamp ts2 = Timestamp.valueOf(ExpectedTS);
  83         assertEquals(ts, ts2, "Error ts1 != ts2");
  84     }
  85 
  86     /*
  87      * Validate two Timestamps created from the same string are equal
  88      */
  89     @Test
  90     public void test02() throws Exception {
  91         String testTS = "2009-01-01 10:50:0";
  92         Timestamp ts = Timestamp.valueOf(testTS);
  93         Timestamp ts2 = Timestamp.valueOf(testTS);
  94         assertEquals(ts, ts2, "Error ts1 != ts2");
  95     }
  96 
  97     /*
  98      * Validate that two Timestamp values one with leading 0s for month and day
  99      * equals same string without the leading 0s.
 100      */
 101     @Test
 102     public void test03() throws Exception {
 103         String testTS = "2009-1-1 10:50:0";
 104         String ExpectedTS = "2009-01-01 10:50:0";
 105         Timestamp ts = Timestamp.valueOf(testTS);
 106         Timestamp ts2 = Timestamp.valueOf(ExpectedTS);
 107         assertEquals(ts, ts2, "Error ts1 != ts2");
 108     }
 109 
 110     /*
 111      * Validate that two Timestamp values one with leading 0s for day omitted
 112      * are equal
 113      */
 114     @Test
 115     public void test04() throws Exception {
 116         String testTS = "2009-01-1 10:50:0";
 117         String ExpectedTS = "2009-01-01 10:50:0";
 118         Timestamp ts = Timestamp.valueOf(testTS);
 119         Timestamp ts2 = Timestamp.valueOf(ExpectedTS);
 120         assertEquals(ts, ts2, "Error ts1 != ts2");
 121     }
 122 
 123     /*
 124      * Validate that two Timestamp values one with leading 0s for month omitted
 125      * and both with leading 0s for seconds omitted are equal
 126      */
 127     @Test
 128     public void test05() throws Exception {
 129         String testTS = "2009-1-01 10:50:0";
 130         String ExpectedTS = "2009-01-01 10:50:0";
 131         Timestamp ts = Timestamp.valueOf(testTS);
 132         Timestamp ts2 = Timestamp.valueOf(ExpectedTS);
 133         assertEquals(ts, ts2, "Error ts1 != ts2");
 134     }
 135 
 136     /*
 137      * Validate that two Timestamp values one with leading 0s for month omitted
 138      */
 139     @Test
 140     public void test06() throws Exception {
 141         String testTS = "2005-1-01 10:20:50.00";
 142         String ExpectedTS = "2005-01-01 10:20:50.00";
 143         Timestamp ts = Timestamp.valueOf(testTS);
 144         Timestamp ts2 = Timestamp.valueOf(ExpectedTS);
 145         assertEquals(ts, ts2, "Error ts1 != ts2");
 146     }
 147 
 148     /*
 149      * Validate that two Timestamp values one created using valueOf and another
 150      * via a constructor are equal
 151      */
 152     @Test
 153     public void test07() {
 154 
 155         Timestamp ts1 = Timestamp.valueOf("1996-12-13 14:15:25.001");
 156         Timestamp ts2 = new Timestamp(96, 11, 13, 14, 15, 25, 1000000);
 157         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
 158     }
 159 
 160     /*
 161      * Validate that two Timestamp values one created using valueOf and another
 162      * via a constructor are equal
 163      */
 164     @Test
 165     public void test08() {
 166         Timestamp ts1 = Timestamp.valueOf("1996-12-13 14:15:25.001");
 167         Timestamp ts2 = new Timestamp(ts1.getTime());
 168         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
 169     }
 170 
 171     /*
 172      * Validate that two Timestamp values one created using valueOf and another
 173      * via a constructor are equal
 174      */
 175     @Test
 176     public void test09() {
 177 
 178         Timestamp ts1 = Timestamp.valueOf("1996-12-13 14:15:25.0");
 179         Timestamp ts2 = new Timestamp(96, 11, 13, 14, 15, 25, 0);
 180         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
 181     }
 182 
 183     /*
 184      * Validate that a Timestamp cannot be equal to null
 185      */
 186     @Test
 187     public void test10() {
 188 
 189         Timestamp ts1 = Timestamp.valueOf("1961-08-30 14:15:25.745634");
 190         Timestamp ts2 = null;
 191         assertFalse(ts1.equals(ts2), "Error ts1 == null");
 192     }
 193 
 194     /*
 195      * Validate that a Timestamp is equal to another timestamp created with the
 196      * using the same value but not equal to a Timestamp which is one day later
 197      */
 198     @Test
 199     public void test11() {
 200 
 201         Timestamp ts1 = Timestamp.valueOf("1996-12-10 12:26:19.12");
 202         Timestamp ts2 = Timestamp.valueOf("1996-12-10 12:26:19.12");
 203         Timestamp ts3 = Timestamp.valueOf("1996-12-11 12:24:19.12");
 204         assertTrue(ts1.equals(ts2) && ts2.equals(ts1), "Error ts1 != ts2");
 205         assertFalse(ts1.equals(ts3) && ts3.equals(ts1), "Error ts1 == ts3");
 206 
 207     }
 208 
 209     /*
 210      * Validate that a Timestamp is equal to itself
 211      */
 212     @Test
 213     public void test12() {
 214         Timestamp ts1 = Timestamp.valueOf("1996-10-15 12:26:19.12");
 215         assertTrue(ts1.equals(ts1), "Error ts1 != ts1");
 216     }
 217 
 218     /*
 219      * Validate that two Timestamps are equal when one is created from the
 220      * toString() of the other
 221      */
 222     @Test(dataProvider = "validTimestampValues")
 223     public void test13(String ts, String expectedTS) {
 224         Timestamp ts1 = Timestamp.valueOf(ts);
 225         Timestamp ts2 = Timestamp.valueOf(ts1.toString());
 226         assertTrue(ts1.equals(ts2) && ts2.equals(ts1)
 227                 && ts1.toString().equals(expectedTS), "Error ts1 != ts2");
 228     }
 229 
 230     // Before Tests
 231     /*
 232      * Validate that Timestamp ts1 is before Timestamp ts2
 233      */
 234     @Test
 235     public void test14() {
 236         Timestamp ts1 = Timestamp.valueOf("1996-12-13 14:15:25.745634");
 237         Timestamp ts2 = Timestamp.valueOf("1996-12-13 15:15:25.645634");
 238         assertTrue(ts1.before(ts2), "Error ts1 not before ts2");
 239     }
 240 
 241     /*
 242      * Validate that Timestamp ts1 is before Timestamp ts2
 243      */
 244     @Test
 245     public void test15() {
 246         Timestamp ts1 = Timestamp.valueOf("1961-08-30 14:15:25");
 247         Timestamp ts2 = Timestamp.valueOf("1999-12-13 15:15:25");
 248         assertTrue(ts1.before(ts2), "Error ts1 not before ts2");
 249     }
 250 
 251     /*
 252      * Validate that Timestamp ts1 is before Timestamp ts2
 253      */
 254     @Test
 255     public void test16() {
 256 
 257         Timestamp ts1 = Timestamp.valueOf("1999-12-13 14:15:25.745634");
 258         Timestamp ts2 = Timestamp.valueOf("1999-11-13 15:15:25.645634");
 259         assertFalse(ts1.before(ts2), "Error ts1 before ts2");
 260     }
 261 
 262     /*
 263      * Validate that a NullPointerException is thrown if a null is passed to
 264      * the before method
 265      */
 266     @Test(expectedExceptions = NullPointerException.class)
 267     public void test17() throws Exception {
 268         Timestamp ts1 = Timestamp.valueOf("1996-12-13 14:15:25.745634");
 269         ts1.before(null);
 270     }
 271 
 272     /*
 273      * Validate a Timestamp cannot be before itself
 274      */
 275     @Test
 276     public void test18() {
 277         Timestamp ts1 = Timestamp.valueOf("1999-11-10 12:26:19.3456543");
 278         assertFalse(ts1.before(ts1), "Error ts1 before ts1!");
 279     }
 280 
 281     /*
 282      * Create 3 Timestamps and make sure the 1st is before the other two
 283      * Timestamps which are each greater than the one before it
 284      */
 285     @Test
 286     public void test19() {
 287 
 288         Timestamp ts1 = new Timestamp(1234560000);
 289         Timestamp ts2 = new Timestamp(1234567000);
 290         Timestamp ts3 = new Timestamp(1234569000);
 291         assertTrue(ts1.before(ts2) && ts2.before(ts3) && ts1.before(ts3));
 292     }
 293 
 294     /*
 295      * Validate that Timestamp ts1 is not after Timestamp ts2
 296      */
 297     @Test
 298     public void test20() {
 299         Timestamp ts1 = Timestamp.valueOf("1999-12-13 14:15:25.745634");
 300         Timestamp ts2 = Timestamp.valueOf("1999-12-13 15:15:25.645634");
 301         assertFalse(ts1.after(ts2), "Error ts1 is after ts2");
 302 
 303     }
 304 
 305     /*
 306      * Validate that Timestamp ts1 is after Timestamp ts2
 307      */
 308     @Test
 309     public void test21() {
 310         Timestamp ts1 = Timestamp.valueOf("1996-12-13 14:15:25.745634");
 311         Timestamp ts2 = Timestamp.valueOf("1996-11-13 15:15:25.645634");
 312         assertTrue(ts1.after(ts2), "Error ts1 not after ts2");
 313     }
 314 
 315     /*
 316      * Validate that a NullPointerException is thrown if a null is passed to the
 317      * after method
 318      */
 319     @Test(expectedExceptions = NullPointerException.class)
 320     public void test22() throws Exception {
 321         Timestamp ts1 = Timestamp.valueOf("1966-08-30 08:08:08");
 322         ts1.after(null);
 323     }
 324 
 325     /*
 326      * Validate that a Timestamp cannot be after itself
 327      */
 328     @Test
 329     public void test23() {
 330         Timestamp ts1 = Timestamp.valueOf("1999-11-10 12:26:19.3456543");
 331         assertFalse(ts1.after(ts1), "Error ts1 is after itself");
 332     }
 333 
 334     /*
 335      * Validate that a Timestamp after() works correctly with Timestamp created
 336      * using milliseconds
 337      */
 338     @Test
 339     public void test24() {
 340 
 341         Timestamp ts1 = new Timestamp(1234568000);
 342         Timestamp ts2 = new Timestamp(1234565000);
 343         Timestamp ts3 = new Timestamp(1234562000);
 344         assertTrue(ts1.after(ts2) && ts2.after(ts3) && ts1.after(ts3));
 345     }
 346 
 347     /*
 348      * Validate compareTo returns 0 for Timestamps that are the same
 349      */
 350     @Test
 351     public void test25() {
 352         Timestamp ts1 = Timestamp.valueOf("1966-08-30 08:08:08");
 353         Timestamp ts2 = new Timestamp(ts1.getTime());
 354         assertTrue(ts1.compareTo(ts2) == 0, "Error ts1 != ts2");
 355     }
 356 
 357     /*
 358      * Validate compareTo returns -1 for when the 1st Timestamp is earlier than
 359      * the 2nd Timestamp
 360      */
 361     @Test
 362     public void test26() {
 363         Timestamp ts1 = Timestamp.valueOf("1966-08-30 08:08:08");
 364         Timestamp ts2 = new Timestamp(ts1.getTime() + 1000);
 365         assertTrue(ts1.compareTo(ts2) == -1, "Error ts1 not before ts2");
 366         assertTrue(ts2.compareTo(ts1) == 1, "Error ts1 is not before ts2");
 367     }
 368 
 369     /*
 370      * Validate compareTo returns 1 for when the 1st Timestamp is later than the
 371      * 2nd Timestamp
 372      */
 373     @Test
 374     public void test27() {
 375         Timestamp ts1 = Timestamp.valueOf("1966-08-30 08:08:08");
 376         Timestamp ts2 = new Timestamp(ts1.getTime() - 1000);
 377         assertTrue(ts1.compareTo(ts2) == 1, "Error ts1 not after ts2");
 378         assertTrue(ts2.compareTo(ts1) == -1, "Error ts1 not after ts2");
 379     }
 380 
 381     /*
 382      * Validate compareTo returns 0 for Timestamps that are the same
 383      */
 384     @Test
 385     public void test28() {
 386         Timestamp ts1 = Timestamp.valueOf("1966-08-30 08:08:08");
 387         java.util.Date ts2 = new java.util.Date(ts1.getTime());
 388         assertTrue(ts1.compareTo(ts2) == 0, "Error ts1 != ts2");
 389     }
 390 
 391     /*
 392      * Validate compareTo returns 0 for Timestamps that are the same
 393      */
 394     @Test
 395     public void test29() {
 396         Timestamp ts1 = Timestamp.valueOf("1966-08-30 08:08:08");
 397         java.util.Date d = new java.util.Date(ts1.getTime());
 398         assertFalse(ts1.equals(d), "Error ts1 == d");
 399     }
 400 
 401     /*
 402      * Validate compareTo returns 0 for Timestamps that are the same
 403      */
 404     @Test
 405     public void test30() {
 406         Timestamp ts1 = Timestamp.valueOf("1966-08-30 08:08:08");
 407         java.util.Date d = new Timestamp(ts1.getTime());
 408         assertTrue(ts1.equals(d), "Error ts1 != d");
 409     }
 410 
 411     /*
 412      * Validate equals returns false when a Date object is passed to equals
 413      */
 414     @Test
 415     public void test31() {
 416         Timestamp ts1 = Timestamp.valueOf("1966-08-30 08:08:08");
 417         Date d = new Date(ts1.getTime());
 418         assertFalse(ts1.equals(d), "Error ts1 != d");
 419     }
 420 
 421     /*
 422      * Validate equals returns false when a Date object is passed to equals
 423      */
 424     @Test
 425     public void test32() {
 426         Timestamp ts1 = Timestamp.valueOf("1966-08-30 08:08:08");
 427         java.util.Date d = new Date(ts1.getTime());
 428         assertFalse(ts1.equals(d), "Error ts1 != d");
 429     }
 430 
 431     /*
 432      * Validate equals returns false when a Time object is passed to equals
 433      */
 434     @Test
 435     public void test33() {
 436         Timestamp ts1 = Timestamp.valueOf("1966-08-30 08:08:08");
 437         Time t1 = new Time(ts1.getTime());
 438         assertFalse(ts1.equals(t1), "Error ts1 == t1");
 439     }
 440 
 441     /*
 442      * Validate equals returns false when a String object is passed to equals
 443      */
 444     @Test
 445     public void test34() {
 446         Timestamp ts1 = Timestamp.valueOf("1966-08-30 08:08:08");
 447         assertFalse(ts1.equals("1966-08-30 08:08:08"), "Error ts1 == a String");
 448     }
 449 
 450     /*
 451      * Validate getTime() returns the same value from 2 timeStamps created by
 452      */
 453     @Test
 454     public void test35() {
 455         Timestamp ts1 = Timestamp.valueOf("1966-08-30 08:08:08");
 456         Timestamp ts2 = Timestamp.valueOf("1966-08-30 08:08:08");
 457         assertTrue(ts2.getTime() == ts1.getTime(),
 458                 "ts1.getTime() != ts2.getTime()");
 459         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
 460     }
 461 
 462     /*
 463      * Validate getTime() returns the same value from 2 timeStamps when
 464      * setTime() is used to specify the same value for both Timestamps
 465      */
 466     @Test
 467     public void test36() {
 468         Timestamp ts1 = Timestamp.valueOf("1966-08-30 08:08:08");
 469         Timestamp ts2 = Timestamp.valueOf("1961-08-30 00:00:00");
 470         ts2.setTime(ts1.getTime());
 471         assertTrue(ts2.getTime() == ts1.getTime(),
 472                 "ts1.getTime() != ts2.getTime()");
 473         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
 474     }
 475 
 476     /*
 477      * Validate an IllegalArgumentException is thrown for an invalid nanos value
 478      */
 479     @Test(expectedExceptions = IllegalArgumentException.class)
 480     public void test38() throws Exception {
 481         Timestamp ts1 = Timestamp.valueOf("1961-08-30 00:00:00");
 482         ts1.setNanos(-1);
 483 
 484     }
 485 
 486     /*
 487      * Validate an IllegalArgumentException is thrown for an invalid nanos value
 488      */
 489     @Test(expectedExceptions = IllegalArgumentException.class)
 490     public void test39() throws Exception {
 491         int nanos = 999999999;
 492         Timestamp ts1 = Timestamp.valueOf("1961-08-30 00:00:00");
 493         ts1.setNanos(nanos + 1);
 494     }
 495 
 496     /*
 497      * Validate you can set nanos to 999999999
 498      */
 499     @Test
 500     public void test40() throws Exception {
 501         int nanos = 999999999;
 502         Timestamp ts1 = Timestamp.valueOf("1961-08-30 00:00:00");
 503         ts1.setNanos(nanos);
 504         assertTrue(ts1.getNanos() == nanos, "Error Invalid Nanos value");
 505     }
 506 
 507     /*
 508      * Validate you can set nanos to 0
 509      */
 510     @Test
 511     public void test41() throws Exception {
 512         int nanos = 0;
 513         Timestamp ts1 = Timestamp.valueOf("1961-08-30 00:00:00");
 514         ts1.setNanos(nanos);
 515         assertTrue(ts1.getNanos() == nanos, "Error Invalid Nanos value");
 516     }
 517 
 518     /*
 519      * Validate that a Timestamp made from a LocalDateTime are equal
 520      */
 521     @Test
 522     public void test42() throws Exception {
 523         Timestamp ts1 = Timestamp.valueOf("1961-08-30 00:00:00");
 524         LocalDateTime ldt = ts1.toLocalDateTime();
 525         Timestamp ts2 = Timestamp.valueOf(ldt);
 526         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
 527     }
 528 
 529     /*
 530      * Validate that a Timestamp LocalDateTime value, made from a LocalDateTime
 531      * are equal
 532      */
 533     @Test
 534     public void test43() throws Exception {
 535         LocalDateTime ldt = LocalDateTime.now();
 536         Timestamp ts2 = Timestamp.valueOf(ldt);
 537         assertTrue(ldt.equals(ts2.toLocalDateTime()),
 538                 "Error LocalDateTime values are not equal");
 539     }
 540 
 541     /*
 542      * Validate an NPE occurs when a null LocalDateTime is passed to valueOF
 543      */
 544     @Test(expectedExceptions = NullPointerException.class)
 545     public void test44() throws Exception {
 546         LocalDateTime ldt = null;
 547         Timestamp.valueOf(ldt);
 548     }
 549 
 550     /*
 551      * Validate that a Timestamp made from a Instant are equal
 552      */
 553     @Test
 554     public void test45() throws Exception {
 555         Timestamp ts1 = Timestamp.valueOf("1961-08-30 00:00:00");
 556         Instant instant = ts1.toInstant();
 557         Timestamp ts2 = Timestamp.from(instant);
 558         assertTrue(ts1.equals(ts2), "Error ts1 != ts2");
 559     }
 560 
 561     /*
 562      * Validate that a Timestamp made from a Instant are equal
 563      */
 564     @Test
 565     public void test46() throws Exception {
 566         Instant instant = Instant.now();
 567         Timestamp ts2 = Timestamp.from(instant);
 568         assertTrue(instant.equals(ts2.toInstant()),
 569                 "Error Instant values do not match");
 570     }
 571 
 572     /*
 573      * Validate an NPE occurs when a null instant is passed to from
 574      */
 575     @Test(expectedExceptions = NullPointerException.class)
 576     public void test47() throws Exception {
 577         Instant instant = null;
 578         Timestamp.from(instant);
 579     }
 580 
 581     // Added SQE tests
 582     /*
 583      * Create a Timestamp and a 2nd Timestamp that is 1 month earlier and
 584      * validate that it is not before or after the original Timestamp
 585      */
 586     @Test
 587     public void test48() {
 588         Calendar cal = Calendar.getInstance();
 589         Timestamp ts1 = new Timestamp(System.currentTimeMillis());
 590         cal.setTimeInMillis(ts1.getTime());
 591         cal.add(Calendar.MONTH, -1);
 592         cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
 593         Timestamp ts2 = new Timestamp(cal.getTimeInMillis());
 594         assertFalse(ts1.before(ts2) || ts2.after(ts1));
 595     }
 596 
 597     /*
 598      * Create two Timestamps and validate that compareTo returns 1 to indicate
 599      * the 1st Timestamp is greater than the 2nd Timestamp
 600      */
 601     @Test
 602     public void test49() {
 603         Calendar cal = Calendar.getInstance();
 604         Timestamp ts1 = new Timestamp(System.currentTimeMillis());
 605         cal.setTimeInMillis(ts1.getTime());
 606         cal.add(Calendar.MONTH, -1);
 607         cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
 608         Timestamp ts2 = new Timestamp(cal.getTimeInMillis());
 609         assertTrue(ts1.compareTo(ts2) == 1);
 610     }
 611 
 612     /*
 613      * Create two Timestamps and validate that the 1st Timestamp is not equal to
 614      * the 2nd Timestamp but equal to itself
 615      */
 616     @Test
 617     public void test50() {
 618         Calendar cal = Calendar.getInstance();
 619         Timestamp ts1 = new Timestamp(System.currentTimeMillis());
 620         cal.setTimeInMillis(ts1.getTime());
 621         cal.add(Calendar.MONTH, -1);
 622         cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
 623         Timestamp ts2 = new Timestamp(cal.getTimeInMillis());
 624         assertTrue(!ts1.equals(ts2) && ts1.equals(ts1));
 625     }
 626 
 627     /*
 628      * Validate that two Timestamps are equal when one is created from the
 629      * toString() of the other
 630      */
 631     @Test(dataProvider = "validateNanos")
 632     public void test51(String ts, int nanos) {
 633         Timestamp ts1 = Timestamp.valueOf(ts);
 634         Timestamp ts2 = Timestamp.valueOf(ts1.toString());
 635         assertTrue(ts1.getNanos() == nanos && ts1.equals(ts2),
 636                 "Error with Nanos");
 637     }
 638 
 639     @Test(dataProvider = "validTimestampLongValues")
 640     public void test52(long value, String ts) {
 641         Timestamp ts1 = new Timestamp(value);
 642         assertEquals(ts1.toString(), ts, "ts1.toString() != ts");
 643     }
 644 
 645     /*
 646      * DataProvider used to provide Timestamps which are not valid and are used
 647      * to validate that an IllegalArgumentException will be thrown from the
 648      * valueOf method
 649      */
 650     @DataProvider(name = "invalidTimestampValues")
 651     private Object[][] invalidTimestampValues() {
 652         return new Object[][]{
 653             {"2009-11-01-01 10:50:01"},
 654             {"aaaa-11-01-01 10:50"},
 655             {"aaaa-11-01 10:50"},
 656             {"1961--30 00:00:00"},
 657             {"--30 00:00:00"},
 658             {"-- 00:00:00"},
 659             {"1961-1- 00:00:00"},
 660             {"2009-11-01"},
 661             {"10:50:01"},
 662             {"1961-a-30 00:00:00"},
 663             {"1961-01-bb 00:00:00"},
 664             {"1961-08-30 00:00:00."},
 665             {"1961-08-30 :00:00"},
 666             {"1961-08-30 00::00"},
 667             {"1961-08-30 00:00:"},
 668             {"1961-08-30 ::"},
 669             {"1961-08-30 0a:00:00"},
 670             {"1961-08-30 00:bb:00"},
 671             {"1961-08-30 00:01:cc"},
 672             {"1961-08-30 00:00:00.01a"},
 673             {"1961-08-30 00:00:00.a"},
 674             {"1996-12-10 12:26:19.1234567890"},
 675             {null}
 676         };
 677     }
 678 
 679     /*
 680      * DataProvider used to provide Timestamps which are  valid and are used
 681      * to validate that an IllegalArgumentException will not be thrown from the
 682      * valueOf method and the corect value from toString() is returned
 683      */
 684     @DataProvider(name = "validTimestampValues")
 685     private Object[][] validTimestampValues() {
 686         return new Object[][]{
 687             {"1961-08-30 00:00:00", "1961-08-30 00:00:00.0"},
 688             {"1961-08-30 11:22:33", "1961-08-30 11:22:33.0"},
 689             {"1961-8-30 00:00:00", "1961-08-30 00:00:00.0"},
 690             {"1966-08-1 00:00:00", "1966-08-01 00:00:00.0"},
 691             {"1996-12-10 12:26:19.1", "1996-12-10 12:26:19.1"},
 692             {"1996-12-10 12:26:19.12", "1996-12-10 12:26:19.12"},
 693             {"1996-12-10 12:26:19.123", "1996-12-10 12:26:19.123"},
 694             {"1996-12-10 12:26:19.1234", "1996-12-10 12:26:19.1234"},
 695             {"1996-12-10 12:26:19.12345", "1996-12-10 12:26:19.12345"},
 696             {"1996-12-10 12:26:19.123456", "1996-12-10 12:26:19.123456"},
 697             {"1996-12-10 12:26:19.1234567", "1996-12-10 12:26:19.1234567"},
 698             {"1996-12-10 12:26:19.12345678", "1996-12-10 12:26:19.12345678"},
 699             {"1996-12-10 12:26:19.123456789", "1996-12-10 12:26:19.123456789"},
 700             {"1996-12-10 12:26:19.000000001", "1996-12-10 12:26:19.000000001"},
 701             {"1996-12-10 12:26:19.000000012", "1996-12-10 12:26:19.000000012"},
 702             {"1996-12-10 12:26:19.000000123", "1996-12-10 12:26:19.000000123"},
 703             {"1996-12-10 12:26:19.000001234", "1996-12-10 12:26:19.000001234"},
 704             {"1996-12-10 12:26:19.000012345", "1996-12-10 12:26:19.000012345"},
 705             {"1996-12-10 12:26:19.000123456", "1996-12-10 12:26:19.000123456"},
 706             {"1996-12-10 12:26:19.001234567", "1996-12-10 12:26:19.001234567"},
 707             {"1996-12-10 12:26:19.12345678", "1996-12-10 12:26:19.12345678"},
 708             {"1996-12-10 12:26:19.0", "1996-12-10 12:26:19.0"},
 709             {"1996-12-10 12:26:19.01230", "1996-12-10 12:26:19.0123"}
 710         };
 711     }
 712 
 713     @DataProvider(name = "validTimestampLongValues")
 714     private Object[][] validTimestampLongValues() {
 715         return new Object[][]{
 716             {1L, "1970-01-01 01:00:00.001"},
 717             {-3600*1000L - 1, "1969-12-31 23:59:59.999"},
 718             {-(20000L*365*24*60*60*1000), "18018-08-28 01:00:00.0"},
 719             {Timestamp.valueOf("1961-08-30 11:22:33").getTime(), "1961-08-30 11:22:33.0"},
 720             {Timestamp.valueOf("1961-08-30 11:22:33.54321000").getTime(), "1961-08-30 11:22:33.543"}, // nanoprecision lost
 721             {new Timestamp(114, 10, 10, 10, 10, 10, 100000000).getTime(), "2014-11-10 10:10:10.1"},
 722             {new Timestamp(0, 10, 10, 10, 10, 10, 100000).getTime(), "1900-11-10 10:10:10.0"}, // nanoprecision lost
 723             {new Date(114, 10, 10).getTime(), "2014-11-10 00:00:00.0"},
 724             {new Date(0, 10, 10).getTime(), "1900-11-10 00:00:00.0"},
 725             {LocalDateTime.of(1960, 10, 10, 10, 10, 10, 50000).atZone(ZoneId.of("America/Los_Angeles"))
 726                 .toInstant().toEpochMilli(), "1960-10-10 19:10:10.0"},
 727 
 728             // millisecond timestamps wraps around at year 1, so Long.MIN_VALUE looks similar
 729             // Long.MAX_VALUE, while actually representing 292278994 BCE
 730             {Long.MIN_VALUE, "292278994-08-17 08:12:55.192"},
 731             {Long.MAX_VALUE + 1, "292278994-08-17 08:12:55.192"},
 732             {Long.MAX_VALUE, "292278994-08-17 08:12:55.807"},
 733             {Long.MIN_VALUE - 1, "292278994-08-17 08:12:55.807"},
 734 
 735             // wrap around point near 0001-01-01, test that we never get a negative year:
 736             {-(1970L*365*24*60*60*1000), "0001-04-25 01:00:00.0"},
 737             {-(1970L*365*24*60*60*1000 + 115*24*60*60*1000L), "0001-12-31 01:00:00.0"},
 738             {-(1970L*365*24*60*60*1000 + 115*24*60*60*1000L - 23*60*60*1000L), "0001-01-01 00:00:00.0"},
 739 
 740             {LocalDateTime.of(0, 1, 1, 10, 10, 10, 50000).atZone(ZoneId.of("America/Los_Angeles"))
 741                 .toInstant().toEpochMilli() - 2*24*60*60*1000L, "0001-01-01 19:03:08.0"}, // 1 BCE
 742             {LocalDateTime.of(0, 1, 1, 10, 10, 10, 50000).atZone(ZoneId.of("America/Los_Angeles"))
 743                 .toInstant().toEpochMilli() - 3*24*60*60*1000L, "0002-12-31 19:03:08.0"} // 2 BCE
 744         };
 745     }
 746 
 747     /*
 748      * DataProvider used to provide Timestamp and Nanos values in order to
 749      * validate that the correct Nanos value is generated from the specified
 750      * Timestamp
 751      */
 752     @DataProvider(name = "validateNanos")
 753     private Object[][] validateNanos() {
 754         return new Object[][]{
 755             {"1961-08-30 00:00:00", 0},
 756             {"1996-12-10 12:26:19.1", 100000000},
 757             {"1996-12-10 12:26:19.12", 120000000},
 758             {"1996-12-10 12:26:19.123", 123000000},
 759             {"1996-12-10 12:26:19.1234", 123400000},
 760             {"1996-12-10 12:26:19.12345", 123450000},
 761             {"1996-12-10 12:26:19.123456", 123456000},
 762             {"1996-12-10 12:26:19.1234567", 123456700},
 763             {"1996-12-10 12:26:19.12345678", 123456780},
 764             {"1996-12-10 12:26:19.123456789", 123456789},
 765             {"1996-12-10 12:26:19.000000001", 1},
 766             {"1996-12-10 12:26:19.000000012", 12},
 767             {"1996-12-10 12:26:19.000000123", 123},
 768             {"1996-12-10 12:26:19.000001234", 1234},
 769             {"1996-12-10 12:26:19.000012345", 12345},
 770             {"1996-12-10 12:26:19.000123456", 123456},
 771             {"1996-12-10 12:26:19.001234567", 1234567},
 772             {"1996-12-10 12:26:19.012345678", 12345678},
 773             {"1996-12-10 12:26:19.0", 0},
 774             {"1996-12-10 12:26:19.01230", 12300000}
 775         };
 776     }
 777 }